给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:”0.1.2.201” 和 “192.168.1.1” 是 有效的 IP 地址,但是 “0.011.255.245”、”192.168.1.312” 和 “192.168@1.1” 是 无效的 IP 地址。
示例 1:
输入:s = “25525511135”
输出:[“255.255.11.135”,”255.255.111.35”]
示例 2:
输入:s = “0000”
输出:[“0.0.0.0”]
示例 3:
输入:s = “1111”
输出:[“1.1.1.1”]
示例 4:
输入:s = “010010”
输出:[“0.10.0.10”,”0.100.1.0”]
示例 5:
输入:s = “101023”
输出:[“1.0.10.23”,”1.0.102.3”,”10.1.0.23”,”10.10.2.3”,”101.0.2.3”]
提示:
0 <= s.length <= 3000
s 仅由数字组成
解法一:DFS
利用DFS思想在字符串上完成搜索。从字符串起始位置开始,先找到所有0~255范围内的后续串,每一个串构成当前IP段,然后对剩余段做相同操作。共需执行至深度为4或者字符串已经消耗完。
注意构造IP段时的特殊情况,即IP段起始为0时,该段只能为0。
class Solution:def restoreIpAddresses(self, s: str) -> List[str]:ans, segs = [], [0, 0, 0, 0]def dfs(start, depth):# 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案if depth == 4:if start == len(s):ans.append(".".join(str(seg) for seg in segs))return# 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯if start == len(s):return# 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0if s[start] == "0":segs[depth] = 0dfs(start + 1, depth + 1)# 一般情况,枚举每一种可能性并递归seg = 0for i in range(start, len(s)):seg = seg * 10 + (ord(s[i]) - ord("0"))if 0 < seg <= 255:segs[depth] = segdfs(i + 1, depth + 1)else:breakdfs(0, 0)return ans
函数签名改为dfs(s),这时segs需要回溯,避免状态污染后面的查找。
class Solution:def restoreIpAddresses(self, s: str) -> List[str]:ans = []segs = []def dfs(s):# 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案if len(segs) == 4:if not s:ans.append(".".join(str(seg) for seg in segs))return# 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯if not s:return# 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0if s[0] == "0":segs.append(0)dfs(s[1:])segs.pop()# 一般情况,枚举每一种可能性并递归seg = 0for i, c in enumerate(s):seg = seg * 10 + (ord(c) - ord("0"))if 0 < seg <= 255:segs.append(seg)dfs(s[i+1:])segs.pop()else:returndfs(s)return ans
