题目描述
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
示例:
输入: “25525511135”
输出: [“255.255.11.135”, “255.255.111.35”]
前不久在在线面试腾讯时碰到过这题,10分钟解题时间,当时一时紧张没写出来,只知道这个题目要用用到回溯算法,回来仔细想了2个解法。
解法一:回溯算法
分析:
ip地址格式规则:
- 包含4部分,如 xx.xx.xx.xx
- 每一部分可以是1位、2位、3位数字。
- 当大于2位时,不能以0开头,同时小于256。如1.01.0.1、1.256.1.1 都是不合法的
所以我们分4次去给的字符串取值,每次取值有三种情况:取1位、取2位、取3位,取值的同时要判断一下每一位是否符合条件3,然后结束的条件是取够4次,取够之后再判断一下剩余字符串是否还有值,有的话就说明本次取值路径不符合,直接return,如给的123456,某次取值路径是tmp=1.2.3.4,s=56,这就不符合规则了。
def get_all_ip(s: str) -> list:
# 定义一个列表,用来存储生成的ip
result = []
def backtrack(s: str, tmp: str):
"""s 是需要回溯的字符串,tmp用来记录回溯“路径” """
if tmp.count('.') == 4: # 统计取了几次值,当tmp中有4个'.'时,表示已经取够了
if not s: # 这时候判断一下s是不是空,不是空的话就不符合,空的话就把tmp加入到结果集result
result.append(tmp[:-1])
return
# 取1位,这时候长度大于0
if len(s) > 0:
# 把剩余的字符串即s[1:]继续递归,同时把s[0]加入到路径记录变量tmp
backtrack(s[1:], tmp + s[0] + '.')
# 取2位,这时候长度要大于1,且首位不为0
if len(s) > 1 and s[0] != '0':
# 把剩余的字符串即s[2:]继续递归,同时把s[:2]加入到路径记录变量tmp
backtrack(s[2:], tmp + s[:2] + '.')
# 取3位,这时候长度要大于2,且首位不为0,且要小于256
if len(s) > 2 and s[0] != '0' and int(s[:3]) < 256:
# 把剩余的字符串即s[3:]继续递归,同时把s[:3]加入到路径记录变量tmp
backtrack(s[3:], tmp + s[:3] + '.')
backtrack(s, '')
return result
解法二:暴力法
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
n = len(s)
res = []
# 判读是否满足ip的条件
def helper(tmp):
if not tmp or (tmp[0] == "0" and len(tmp) > 1) or int(tmp) > 255:
return False
return True
# 三个循环,把数字分成四份
for i in range(3):
for j in range(i + 1, i + 4):
for k in range(j + 1, j + 4):
if i < n and j < n and k < n:
tmp1 = s[:i + 1]
tmp2 = s[i + 1:j + 1]
tmp3 = s[j + 1:k + 1]
tmp4 = s[k + 1:]
# print(tmp1, tmp2, tmp3, tmp4)
if all(map(helper, [tmp1, tmp2, tmp3, tmp4])):
res.append(tmp1 + "." + tmp2 + "." + tmp3 + "." + tmp4)
return res