代码随想录算法训练营第二十五天 |回溯算法part04
491 递增子序列
可以过,但是时间复杂度很高。
nums = [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1]
def backtracking(nums,path,result,index):
if len(path) > 1 :
if path == sorted(path):
if path not in result: # 确保结果中没有重复组合
result.append(path[:])
for i in range(index,len(nums)):
if i > index and nums[i] == nums[i-1] :
continue
path.append(nums[i])
backtracking(nums,path,result,i+1)
path.pop()
result = []
backtracking(nums,[],result,0)
print(result)
参考答案1:利用set去重
def findSubsequences(self, nums):
result = []
path = []
self.backtracking(nums, 0, path, result)
return result
def backtracking(self, nums, startIndex, path, result):
if len(path) > 1:
result.append(path[:]) # 注意要使用切片将当前路径的副本加入结果集
# 注意这里不要加return,要取树上的节点
uset = set() # 使用集合对本层元素进行去重
for i in range(startIndex, len(nums)):
if (path and nums[i] < path[-1]) or nums[i] in uset:
continue
uset.add(nums[i]) # 记录这个元素在本层用过了,本层后面不能再用了
path.append(nums[i])
self.backtracking(nums, i + 1, path, result)
path.pop()
参考答案2:利用哈希表去重
注意 used = [0] * 201这一行,其在递归算法内部。
而且不需要归零操作 判断的条件也需要注意
if (path and nums[i] < path[-1]) or used[nums[i] + 100] == 1:
def findSubsequences(self, nums):
result = []
path = []
self.backtracking(nums, 0, path, result)
return result
def backtracking(self, nums, startIndex, path, result):
if len(path) > 1:
result.append(path[:]) # 注意要使用切片将当前路径的副本加入结果集
used = [0] * 201 # 使用数组来进行去重操作,题目说数值范围[-100, 100]
for i in range(startIndex, len(nums)):
if (path and nums[i] < path[-1]) or used[nums[i] + 100] == 1:
continue # 如果当前元素小于上一个元素,或者已经使用过当前元素,则跳过当前元素
used[nums[i] + 100] = 1 # 标记当前元素已经使用过
path.append(nums[i]) # 将当前元素加入当前递增子序列
self.backtracking(nums, i + 1, path, result)
path.pop()
15 全排列
思路:和之前的回溯一样,首先我们先写出来可以算出全部情况的代码,如下:
nums = [1,2,3]
def backtracking(nums,result,path):
if len(nums) == len(path):
result.append(path[:])
return
for i in range(len(nums)):
path.append(nums[i])
backtracking(nums,result,path)
path.pop()
result = []
backtracking(nums,result,[])
print(result)
然后我们需要想办法去重,一个数如果这次被用了,那么下次就不能用了,所以用used表记录一下,完整代码如下:
nums = [1,2,3]
def backtracking(nums,result,path,used):
if len(nums) == len(path):
result.append(path[:])
return
for i in range(len(nums)):
if used[i]:
continue
used[i] = True
path.append(nums[i])
backtracking(nums,result,path,used)
path.pop()
used[i] = False
result = []
used = [False] * len(nums)
backtracking(nums,result,[],used)
print(result)
16 全排列II
nums = [1]
def backtracking(nums,result,path,used):
if len(path) == len(nums):
result.append(path[:])
return
for i in range(len(nums)):
if (i > 0 and nums[i] == nums[i-1] and not used[i-1]) or used[i]:
continue
used[i] = True
path.append(nums[i])
backtracking(nums,result,path,used)
path.pop()
used[i] = False
nums.sort()
used = [False] * len(nums)
result = []
backtracking(nums,result,[],used)
print(result)