93.复原IP地址
思路
代码
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
res = []
path = []
def helper(index):
if index == len(s) and len(path) == 4:
res.append(".".join(path))
return
if len(path) > 4:
return
for i in range(index, min(len(s), index + 3)):
temp = s[index:i+1]
if self.isValid(temp):
path.append(temp)
helper(i + 1)
path.pop()
helper(0)
return res
def isValid(self, s):
if len(s) > 1 and s[0] == '0':
return False
num = int(s)
return 0 <= num <= 255
复杂度分析
- 时间复杂度:
O(3^4)
,IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。 - 空间复杂度:
O(n)
78.子集
思路
子集问题和组合问题的不同点在于:
如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
代码
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
def helper(index):
if index > len(nums):
return
res.append(path.copy())
for i in range(index, len(nums)):
path.append(nums[i])
helper(i + 1)
path.pop()
helper(0)
return res
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
path = []
def helper(index):
if index == len(nums):
return
for i in range(index, len(nums)):
path.append(nums[i])
res.append(path.copy())
helper(i + 1)
path.pop()
helper(0)
return res
class Solution:
def subsets(self, nums):
result = []
path = []
self.backtracking(nums, 0, path, result)
return result
def backtracking(self, nums, startIndex, path, result):
result.append(path[:]) # 收集子集,要放在终止添加的上面,否则会漏掉自己
# if startIndex >= len(nums): # 终止条件可以不加
# return
for i in range(startIndex, len(nums)):
path.append(nums[i])
self.backtracking(nums, i + 1, path, result)
path.pop()
这几种都可以。
复杂度分析
- 时间复杂度:
O(n * 2^n)
- 空间复杂度:
O(n)
90.子集II
思路
具体思路和组合求和II 类似,需要先对nums排序,然后树层去重。
代码
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = [[]]
path = []
def helper(index):
for i in range(index, len(nums)):
if i > index and nums[i] == nums[i-1]:
continue
path.append(nums[i])
res.append(path.copy())
helper(i + 1)
path.pop()
helper(0)
return res
复杂度分析
- 时间复杂度:
O(n * 2^n)
- 空间复杂度:
O(n)