本题的思路和昨天的分割回文串一样,都是在回溯之前先判断。
不同点是:
1、终止条件多了一个path节点数==4的判定;
2、判断是否合法不仅是数值比较,还需要判断是否有前置的0。
class Solution(object):
def restoreIpAddresses(self, s):
"""
:type s: str
:rtype: List[str]
"""
res = []
self.backtracking(0, [], res, s)
return res
def backtracking(self, start_idx, path, res, s):
# 终止条件除了到达末尾以外,还需要路径中保存的节点数是4
if start_idx == len(s) and len(path) == 4:
res.append(".".join(path))
return
for i in range(start_idx, len(s)):
# 这里和分割回文数写法一致
if self.is_valid(start_idx, i, s):
path.append(s[start_idx:i+1])
self.backtracking(i+1, path, res, s)
path.pop()
def is_valid(self, start_idx, cur, s):
# 开头是0,后面还有数字为不合法
if s[start_idx] == '0' and cur != start_idx:
return False
cur_value = int(s[start_idx: cur+1])
if cur_value > 255: # 大于255不合法
return False
return True
本题需要保存全部的不重复节点,所以我们不是在遍历到叶子节点的时候再进行res的操作,而是需要在每一次回溯的时候进行res的保存。
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
self.backtracking(0, res, [], nums)
res.append([])
return res
def backtracking(self, start_idx, res, path, nums):
if start_idx == len(nums):
return
for i in range(start_idx, len(nums)):
path.append(nums[i])
self.backtracking(i+1, res, path, nums)
# 每次回溯到上一个节点的时候加入当前的路径
res.append(path[:])
path.pop()
本题是78.子集和40.组合II的杂交题,既要判断去重逻辑,又要保存所有的根节点和叶子节点。
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
# 去重之前先排序,把相同的都放到一起
nums.sort()
self.backtracking(0, nums, [], res)
res.append([])
return res
def backtracking(self, start_idx, nums, path, res):
if start_idx == len(nums):
return
# 和之前的去重逻辑一样,如果当前和之前一致,说明已经被遍历,不需要在找了
for i in range(start_idx, len(nums)):
if i > start_idx and nums[i] == nums[i -1]:
continue
path.append(nums[i])
self.backtracking(i+1, nums, path, res)
# 和上一题的组合一样,需要保存路径上的所有节点
res.append(path[:])
path.pop()
今天的好简单,全是模版题!!!回溯法第一天的模版真的很重要!!!!
第28天完结(终于追上进度了