文档讲解:代码随想录
视频讲解:代码随想录B站账号
状态:看了视频题解和文章解析后做出来了
93.复原IP地址
class Solution:
def isvalid(self, s, start, end):
if start > end:
return False
if s[start] == '0' and start != end:
return False
num = int(s[start:end+1])
return num <= 255
def backtracking(self, s, path, result, startindex):
if startindex == len(s) and len(path) == 4:
result.append('.'.join(path))
return
if len(path) > 4:
return
for i in range(startindex, min(startindex + 3, len(s))):
if self.isvalid(s, startindex, i):
path.append(s[startindex:i+1])
self.backtracking(s, path, result, i+1)
path.pop()
return result
def restoreIpAddresses(self, s: str) -> List[str]:
res = self.backtracking(s, [], [], 0)
return res
第一步:确定函数参数,老几样。
第二步:确定终止条件。这道题的终止条件有两个:
1. startindex==len(s),也就是说已经遍历到了s的最后一个元素。如果不加这个条件那么就无法保证用到s的所有元素,255255255255可能会返回2.5.5.2作为结果,这样就不符合题意了。
2.len(path) == 4,确保path里只有4个元素。因为我们的分割逻辑是有可能分割出多于4个ip部分或少于4个ip部分的,所以这个终止条件也十分有必要。后面的剪枝也是使用了len(path) > 4,这样255255255255再被分割成2.5.5.2.5的时候就会终止了。
第三步:确定单层逻辑。首先需要建立一个isvalid函数来验证当前分割的ip是否符合条件,这个函数有三种不合法情况需要判断:
1. 当start > end。
2. 当字符串由0开头,且0不是最后一位。
3. 字符串代表的数字大于255。
递归的时候传入path和result,startindex++因为不能使用相同元素。
时间复杂度: O(3^4):IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。
空间复杂度: O(n)
78.子集
class Solution:
def backtracking(self, nums, path, result, startindex):
result.append(path[:])
for i in range(startindex, len(nums)):
path.append(nums[i])
self.backtracking(nums, path, result, i+1)
path.pop()
return result
def subsets(self, nums: List[int]) -> List[List[int]]:
res = self.backtracking(nums, [], [], 0)
return res
这道题唯一区别就是没有终止条件,只要是进入递归那path必定是一个解。
题目里要求了结果集的去重,但因为题目给定的input全是unique value,所以并不需要任何去重操作。这道题除这两点之外就没什么好说的了。
时间复杂度: O(n * 2^n)
空间复杂度: O(n)
90.子集II
class Solution:
def backtracking(self, nums, path, result, startindex):
result.append(path[:])
for i in range(startindex, len(nums)):
if i > startindex and nums[i] == nums[i-1]:
continue
path.append(nums[i])
self.backtracking(nums, path, result, i+1)
path.pop()
return result
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums = sorted(nums)
res = self.backtracking(nums, [], [], 0)
return res
子集的两道题和昨天那组题很类似,子集II唯一区别就是题目input中可能存在重复element。那么按照昨天的去重逻辑,先给input排序,然后在树层维度上,如果i>startindex且nums[i] == nums[i-1],就continue。
[1,1,2],在树层阶段遍历第二个1的时候,直接跳过。i>startindex保证了树层。
有了剪枝,实际时间复杂度要比这个少。
时间复杂度: O(n * 2^n)
空间复杂度: O(n)