代码随想录算法训练营第二十五天 |回溯算法part04

83 阅读2分钟

代码随想录算法训练营第二十五天 |回溯算法part04

491 递增子序列

image.png

可以过,但是时间复杂度很高。

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 全排列

image.png

思路:和之前的回溯一样,首先我们先写出来可以算出全部情况的代码,如下:

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

image.png

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)

332 重新安排行程

leetcode.cn/problems/re…

51 N皇后

leetcode.cn/problems/n-…

37 解数独

leetcode.cn/problems/su…