93. 复原 IP 地址
原始题目链接:https://leetcode-cn.com/problems/restore-ip-addresses/
给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 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、分成4段;2、每一段的数字在0到255之间;所以需要使用回溯的方法来解题。设计一个递归函数dfs(seg_id,s_start,s),从字符串s的s_start索引处开始遍历,查找第seg_id段的合法ip,seg_id最大值为4。每一段合法的ip地址满足上述的条件,并且如果4段ip地址都满足并且遍历完了字符串s,就是一种合法的ip地址。特别的,如果遍历到当前的数字为0,则这一段的ip地址就是0。具体实现看代码及注释。
代码实现:
class Solution:
def __init__(self):
self.ans = []
# ip地址一共4段
self.IP_SEG = 4
# 存储合法ip地址的数字
self.legal_ip_num = [0] * self.IP_SEG
def dfs(self, seg_id, s_start, s):
"""
从s[s_start]位置开始,可能的合法ip中第seg_id段是否满足ip地址条件
"""
# 如果4段ip地址都满足并且遍历完了字符串s,就是一种合法的ip地址
if seg_id == self.IP_SEG:
if s_start == len(s):
legal_ip = ".".join(str(seg) for seg in self.legal_ip_num)
self.ans.append(legal_ip)
return
# 没有找全4段ip地址并且字符串已经遍历完,那直接回溯
if seg_id != self.IP_SEG and s_start == len(s):
return
# 每一段ip地址开头是0的情况,遇到0这一段的ip就直接赋值为0
if s[s_start] == '0':
self.legal_ip_num[seg_id] = 0
# 递归调用进入下一段ip和从下一个字符开始遍历
self.dfs(seg_id + 1, s_start + 1, s)
# 一般情况
ip_num = 0
for s_end in range(s_start, len(s)):
# 每次遍历都会向右移动,所以要自增一位,之前的数乘以10再加上当前的数来计算
ip_num = ip_num * 10 + (ord(s[s_end]) - ord('0'))
# 校验是否在0到255之间
if 0 < ip_num <= 255:
# 符合条件则为本段ip
self.legal_ip_num[seg_id] = ip_num
# 进入下一段ip查找,就需递归
self.dfs(seg_id + 1, s_end + 1, s)
else:
break
def restoreIpAddresses(self, s: str):
self.dfs(0, 0, s)
return self.ans
参考文献:
https://leetcode-cn.com/problems/restore-ip-addresses/solution/fu-yuan-ipdi-zhi-by-leetcode-solution/