【面试高频题】难度 2/5,回溯算法经典运用
创始人
2024-03-23 18:44:15
0

题目描述

 

这是 LeetCode 上的 93. 复原 IP 地址 ,难度为 中等

Tag : 「回溯」、「DFS」

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201""192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245""192.168.1.312""192.168@1.1" 是 无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例 1:

输入:s = "25525511135"输出:["255.255.11.135","255.255.111.35"]
复制代码

示例 2:

输入:s = "0000"输出:["0.0.0.0"]
复制代码

示例 3:

输入:s = "101023"输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
复制代码

提示:

  • 1<=s.length<=201 <= s.length <= 201<=s.length<=20
  • s 仅由数字组成

回溯算法

和 131. 分割回文串 一样,同样是一道求所有方案的题目,只能是没有太多优化的「爆搜」做法。

设计递归函数为 void dfs(int idx, int n, List cur),其中 idxn 分别代表当前处理字符串 s 的哪个位置,以及字符串 s 的总长度,而 cur 的则是代表子串 s[0...(idx−1)]s[0 ... (idx - 1)]s[0...(idx−1)] 部分的具体划分方案。

用题目样例 s = "25525511135" 作为 🌰,n 固定为 11,当 idx = 3 时,cur 为 s[0...2]=255s[0...2] = 255s[0...2]=255 部分的划分方案,cur 可能是 [2,5,5][2,55][25,5][255] 之一,在 cur 的基础上,我们继续爆搜剩余部分,即递归执行 dfs(idx, n, cur),算法会将剩余部分的划分方案添加到 cur 上,我们只需要确保每次追加到 cur 的数值符合要求即可(没有前导零 且 范围在 [0,255][0, 255][0,255] 中)。

在单次回溯过程中,我们可以将 idx 作为当前划分数字的左端点,通过枚举的形式找到右端点 j,并将当前数字 s[idx...(j−1)]s[idx ... (j - 1)]s[idx...(j−1)] 加到 cur 中(若合法),回溯到底后再添加到 cur 的元素进行移除。

idx = n 代表整个 s 已经处理完成,若此时 cur 恰好有 444 个元素,说明我们找到了一组合法方案,将其拼接成字符串追加到答案数组中。同时也是由于划分过程中 cur 最多只有 444 个元素,我们可以用此做简单剪枝。

Java 代码:

class Solution {List ans = new ArrayList<>();char[] cs;public List restoreIpAddresses(String s) {cs = s.toCharArray();dfs(0, cs.length, new ArrayList<>());return ans;}void dfs(int idx, int n, List cur) {if (cur.size() > 4) return ;if (idx == n) {if (cur.size() == 4) {StringBuilder sb = new StringBuilder();for (int i = 0; i < 4; i++) sb.append(cur.get(i)).append(".");ans.add(sb.substring(0, sb.length() - 1));}} else {for (int i = idx; i < n; i++) {int t = 0;for (int j = idx; j <= i; j++) t = t * 10 + (cs[j] - '0');if (cs[idx] == '0' && i != idx) break;if (t > 255) break;cur.add(t);dfs(i + 1, n, cur);cur.remove(cur.size() - 1);}}}
}
复制代码

Python 代码:

class Solution:def restoreIpAddresses(self, s: str) -> List[str]:ans = []def dfs(idx, n, cur):if len(cur) > 4:return if idx == n:if len(cur) == 4:ans.append('.'.join(cur))else:for i in range(idx, n):t = 0for j in range(idx, i + 1):t = t * 10 + (ord(s[j]) - ord('0'))if s[idx] == '0' and i != idx:breakif t > 255:breakcur.append(str(t))dfs(i + 1, n, cur)cur.pop()dfs(0, len(s), [])return ans
复制代码

TypeScript 代码:

function restoreIpAddresses(s: string): string[] {const ans = new Array()function dfs(idx: number, n: number, cur: Array): void {if (cur.length > 4) return if (idx == n) {if (cur.length == 4) {let str = ''for (let i = 0; i < 4; i++) str += cur[i] + "."ans.push(str.substring(0, str.length - 1))}} else {for (let i = idx; i < n; i++) {let t = 0for (let j = idx; j <= i; j++) t = t * 10 + (s.charCodeAt(j) - '0'.charCodeAt(0))if (s[idx] == '0' && i != idx) breakif (t > 255) breakcur.push(t)dfs(i + 1, n, cur)cur.pop()}}}dfs(0, s.length, new Array())return ans
}
复制代码
  • 时间复杂度:爆搜不讨论时空复杂度
  • 空间复杂度:爆搜不讨论时空复杂度

最后

这是我们「刷穿 LeetCode」系列文章的第 No.93 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...