文章目录

  • ​​题目描述​​
  • ​​思路分析​​
  • ​​完整代码​​

题目描述

有效 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 地址。
给定一个只包含数字的字符串 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”]

思路分析

一定要。
先做 ​​31. 分割回文串​​ 再做这道题!!!
先做 ​​31. 分割回文串​​ 再做这道题!!!
先做 ​​31. 分割回文串​​ 再做这道题!!!

为啥呢~因为这道题是分割回文串的进阶版,改动的地方不多。

这道题也是分割,而且比上一个字符串分割感觉看上去要清晰一些,也是找组合的题嘛,回溯嘛,你要问我能不能暴力,我只能说, 可以暴力,看到有人这么做了,N层for,写到怀疑人生。

判断IP地址合法性的几个点:

  • IP地址一共是四段组成,中间三个 ‘.’ 分隔符。
  • 每一段有0-3个数字,范围是0-255左闭右闭。
  • 每小段中可以仅有0,但不能有向导0。
def ip_check(ip):
if ip == '0':return True # 可以有0但不能前导0
if ip[0] == '0':return False
if int(ip) > 0 and int(ip) < 256:
return True
else:
return False

老规矩 回溯三步走:

1.确定函数参数:
这里的参数非常简单,就一个值,就是startindex,用于记录下次从哪里开始遍历。当然,这个参数确定要参考所写代码结构和所用编程语言。
2.确定终止条件:
如果path里有4个值了,也就是有4个小段ip了,并且 startindex 已经遍历到最后了,那么此时就加入到答案集res里。

这道题最后有两个小提示,

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

这就意味着在判断ip合法性的时候不需要判断是否是数字字符了。
还有一点就是题目要求不得删改原s字符中的数值,但是题目s所给长度范围又达到20个,而合法ip最大长度也就是每一段都是3个字符,所以最长也就是12个字符,在这里可以设置一个终止条件,就是所给s长度大于12,则直接return。

3.确定循环体:

这道题的循环体和上一道切割回文字符串的循环体基本一样,就是上一题添加答案集之前判断是不是回文的,这道题是判断IP地址是否合法。

完整代码

def restoreIpAddresses(self, s: str):
path = []
res = []
def ip_check(ip):
if ip == '0':return True # 可以有0但不能前导0
if ip[0] == '0':return False
if int(ip) > 0 and int(ip) < 256:
return True
else:
return False
def backtrack(startindex):
# 确定终止条件
if len(s) > 12: # 剪枝,题目所给的s长度为1-20.
return
if len(path) == 4 and startindex == len(s):
res.append(".".join(path[:]))
return
# 递归体
for i in range(len(startindex,len(s))):
ip = s[startindex,i+1]
if ip_check(ip):
path.append(ip)
else:
continue
backtrack(i+1)
ip.pop()
backtrack(0)
return res