一、93.复原IP地址
本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了题目链接/文章讲解:代码随想录
1. 题意
有效的 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 地址。
2. 代码实现
(1)定义全局变量数组result存放合法的结果字符串。
(2)定义递归函数的参数和返回值:传入字符串s,start_index用于下层递归从哪里开始向后切割,pointSum表示一个合法的IP地址有四个整数,所以必须有3个逗号。
(3)确定终止条件:
1)pointSum等于3的时候(此时树的深度为3),就停止递归。加了逗号之后,因为是对前面这个字符串进行合法性判断;此外还剩最后一段,需要对其进行合法性判断。
2)对最后一段字符串进行合法性判断:if语句,调用自定义的合法性判断函数,传入字符串片段,以start_index作为分割线(起始位置),以len(s)-1为终止位置,左闭右闭区间。
3)合法性判断函数:数字前不能有0,区间是0~255,子串里不可以有非法字符。
4)如果合法,则收集这个字符串,最后返回。
(4)单层搜索逻辑:
1)for循环:i 从start_index开始,到s字符串长度为止;
2)进行合法性判断:传入左闭右闭区间,左区间start_index,右区间i。start_index固定,但i会向后移动,这个区间就是我们取出的子串。
3)为子串加上一个逗号,插入到子串后的一个位置;
4)pointSum加1。
5)下一层递归:需要从i+2的位置开始,因为有一个逗号;
6)回溯:去掉逗号,pointSum减去1。
class Solution:
def is_valid(self, s, left, right):
if left > right:
return False
if s[left] == '0' and left != right:
return False
num = 0
for i in range(left, right + 1):
if not s[i].isdigit():
return False
num = 10 * num + int(s[i])
if num > 255:
return False
return True
def backTracking(self, s, current, pointSum, start_index, result):
if pointSum == 3:
if self.is_valid(s, start_index, len(s)-1):
current += s[start_index:]
result.append(current)
return
for i in range(start_index, len(s)):
if self.is_valid(s, start_index, i):
sub = s[start_index : i+1]
self.backTracking(s, current+sub+'.', pointSum+1, i+1, result)
else:
break
def restoreIpAddresses(self, s: str) -> List[str]:
result = []
self.backTracking(s, '', 0, 0, result)
return result
二、78.子集
子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。题目链接/文章讲解:代码随想录
1. 和之前题目的不同
每一层递归都有想要的结果,都需要加入结果集。
2. 代码实现
(1)定义一位数组path存放单个结果,二维数组result存放结果集。
(2)确定递归函数的参数和返回值:参数start_index表示本层递归从哪里开始取数,nums是传入的数组。
(3)确定终止条件:如果start_index大于等于nums数组的大小,那么终止递归,直接return。
(4)单层递归逻辑:for循环,将nums每个元素添加进入path,然后从i+1开始递归下一层,回溯将元素弹出。
class Solution:
def backTracking(self, nums, start_index, path, result):
result.append(path[:])
if start_index >= len(nums):
return
for i in range(start_index, len(nums)):
path.append(nums[i])
self.backTracking(nums, i+1, path, result)
path.pop()
def subsets(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
self.backTracking(nums, 0, path, result)
return result
三、90.子集II
之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。题目链接/文章讲解:代码随想录
代码实现
class Solution:
def backTracking(self, nums, start_index, used, path, result):
result.append(path[:])
if start_index >= len(nums):
return
for i in range(start_index, len(nums)):
if i > 0 and nums[i] == nums[i-1] and not used[i-1]:
continue
path.append(nums[i])
used[i] = 1
self.backTracking(nums, i+1, used, path, result)
used[i] = 0
path.pop()
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
used = [0] * len(nums)
path = []
result = []
self.backTracking(nums, 0, used, path, result)
return result