算法训练第三十二天 | 回溯算法 491.递增子序列 46.全排列 47.全排列 II

回溯算法

代码模板

思路就是通过横向for循环,纵向递归的形式(递归里面嵌for循环套)
在这里插入图片描述
代码模板如下

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择的列表); // 递归
        回溯,撤销处理结果
    }
}

LeetCode 491.递增子序列

题目链接

491.递增子序列

思路

树枝和数层的去重特别注意:

#对树层去重
if nums[i] in used:
    continue
#对树枝去重
if i>0 and nums[i] < nums[i-1]:
	continue

注意uesd与之前的区别,这里是存本轮树层有过的数,之前的uesd存的path出现过的数

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        def backtracking(nums, start_index):
            # 收集结果,同78.子集,仍要置于终止条件之前
            if len(path) > 1:
                # 本题要求所有的节点
                result.append(path[:])
                #return 不能写return 不然不会执行后面的内容 
        
            # Base Case(可忽略)
            if start_index == len(nums):
                return

            # 单层递归逻辑
            # 深度遍历中每一层都会有一个全新的usage_list用于记录本层元素是否重复使用
            used = []
            # 同层横向遍历
            for i in range(start_index, len(nums)):
                # 若当前元素值小于前一个时(非递增)或者曾用过,跳入下一循环
                if (path and nums[i] < path[-1]) or nums[i] in used:
                    continue
                used.append(nums[i])
                path.append(nums[i])
                backtracking(nums, i+1)
                path.pop() 

        backtracking(nums, 0)
        return result

    

LeetCode 46.全排列

题目链接

46.全排列

思路

还是比较模板的,跟组合的区别就是不要写那个startIndex,只要写used做标记,注意pop的时候要把标记改为False

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        used = [False] * len(nums)
        def backtracking(nums, uesd):
            
            if len(path) == len(nums):
                result.append(path[:])
                return 
            for i in range(0, len(nums)):
                if used[i] == True: continue
                path.append(nums[i])
                used[i] = True
                backtracking(nums, used)
                used[i] = False
                path.pop()

        backtracking(nums, used)
        return result

LeetCode 47.全排列 II

题目链接

47.全排列 II

思路

跟组合Ⅱ一致,跟上题的区别在于要对nums排序,continue掉与上一个元素相同并且上一个为False的元素

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums = sorted(nums)
        path = []
        result = []
        used = [False] * len(nums)
        def backtracking(nums, uesd):
            
            if len(path) == len(nums):
                result.append(path[:])
                return 
            for i in range(0, len(nums)):
                if i>0 and nums[i] == nums[i-1] and used[i-1] == False: continue
                if used[i] == True: continue
                path.append(nums[i])
                used[i] = True
                backtracking(nums, used)
                used[i] = False
                path.pop()

        backtracking(nums, used)
        return result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值