leetcode46,47

组合就要求每一次都从0开始,但是要判断该元素究竟有没有用过,以此来规定每个元素只能出现一次。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res=[]
        path=[]
        used=[]
        def backtrack(nums,used):
            if len(path)==len(nums):
                res.append(path[:])

            for i in range(0,len(nums)):#与组合不同,排列这里是从0开始,而不是从start开始,因此不需要start
                if nums[i] in used:#如果已经使用过就跳过。
                    continue
                used.append(nums[i])
                path.append(nums[i])
                backtrack(nums,used)#注意这的used已经更新,因为加入了nums[i]
                path.pop()
                used.pop()
        backtrack(nums,[])
        return res



47

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        res=[]
        path=[]
        used=[0]*len(nums)
        def backtrack(nums,used,path):
            if len(path)==len(nums):
                return res.append(path[:])
            for i in range(0,len(nums)):
                if not used[i]:
                    if i>0 and nums[i]==nums[i-1] and used[i-1]==0:
                        continue
                    used[i]=1
                    path.append(nums[i])
                    backtrack(nums,used,path)
                    path.pop()
                    used[i]=0
        nums=sorted(nums)
        backtrack(nums,used,[])
        return res
    '''明显需要我们同层去重剪枝。这里主要讲解一下
        if i>0 and nums[i]==nums[i-1] and used[i-1]==0:  continue这句话的意思。
        举例[1,1',2]。当第一位选择1的时候,后面选择1'并不会发生重复,但是当第一位选择1的情况遍历完毕。
         我们开始在第一位上选择1'的时候,由于此时1还没有使用,所以遍历结果和第一位是1的时候完全相同。因此我们
         需要跳过。
         如果写成used[i-1]==1也是可以的,但是这样是表示这一个元素的前一个重复元素的used是1,他也是1,跳过。
         这样写是到了叶子结点的时候才被剪掉。相比较于上个方法,这样更冗长费时
         
         具体图解可以看https://leetcode-cn.com/problems/permutations-ii/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liwe-2/'''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值