回溯算法(6)继续练习

我们先接着做这个题:

练习

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

这个意思就是对于顺序不同的也会是不同的答案

我直接写代码 这和我第一个关于回溯的博客是重合的 因为元素是不可以被重复使用的 所以会设置一个used数组 如果这个元素已经被使用过 那就被剪枝 不然的话就可以进栈 然后递归 直到return之后回来 然后再尝试其他的情况

class Solution(object):
    def permute(self, nums):
        res = []
        n = len(nums)
        def backtrack(path,used):
            if len(path) == n:  # 检查当前路径的和
                res.append(path[:])  # 记录合法组合
                return
            # 剪枝条件这个元素是没有用过的 如果这个元素用过那就不可以再用
            for i in range(n):
                if not used[i]:
                    path.append(nums[i])
                    used[i]=True
                    backtrack(path, used)
                    path.pop()
                    used[i]=False
        backtrack([],[False]*n)
        return res
solution=Solution()
result=solution.permute([1,2,3])
print(result)

知识点

这个代码应该没什么说的 都是常规情况 那么为什么这里一定要使用used数组呢?因为在这里的是排列 是允许不同的顺序的 为了避免大家晕 我这里将区别列出

组合:就拿使得总和等于3为例子,顺序不重要 [1,2]和[2,1]是同一个组合 如何去重呢?一般是先对数组进行排序 然后使用i>start和相邻元素相等两个条件来跳过同一层的相等的元素 意思是这个元素只能在其他层 充当这个元素的辅助 配角 不能自己再单开了 单开的资格已经被前面和它相等的元素拿走了 递归的话就是backtrack(i+1,path)既不重复选择当前的元素 也不会回头选 (注意要结合题意 是不是当前元素可以重复选 我这个说的是之前的博客的一道题目)

排列:顺序很重要,不同的顺序就是不同的排列。在初中大概就学过这样的。你想啊 个子高的站前面和站后面这个肯定排列是不一样的 对于排列而言 是不能出现已经使用过的元素使用第二遍的 所以要使用used数组去标记已经使用的元素 避免重复选择同一个元素  backtrack(path) + used(允许任意顺序,但不能重复选)

 

大家要注意二者的区别是什么  组合因为不允许重复组合 所以排序之后 “不回头选”​​ 是 start 实现的(例如 backtrack(i+1, ...)),但去重的核心是跳过同一层的重复数字(在同一层的相同的元素i > start 的含义​​:当前数字不是这一层的第一个选择(即不是 start 指向的位置)所以是跳过同一层) 而对于排列来说 顺序是很重要的 所以元素任意顺序 但是我们要使用used标记已经使用的元素 避免元素重复(刚刚那个题是不包括重复元素的)

一些误区:

1.在排列中使用start

start是使得已经选择的元素不能再单开 控制下一层递归的起始位置(即“不回头选”)去重的话是通过相邻元素相等这样的条件进行控制的   start 防止“回头选”更小的数字(如 [2,1] 被避免,因为 [1,2] 已覆盖) 但是在排列中 这是两个不同的排列 所以这样的话就不符合排列的规则了 不要在排列当中使用start

2.在组合中不使用start

如果在组合中不使用start 会导致已经当配角的元素 下一次又一次当头了 生成两个相同的组合 

关键点就是要明白​i > start 仅表示​​:当前数字不是这一层的第一个选择(即 i 不是 start)但是它无法判断重复 要是想判断重复 必须结合 ​nums[i] == nums[i-1]

码字不易 如果你喜欢这篇文章 欢迎点赞收藏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值