[leetcode]排列&组合&子集(python)

排列

全排列不重复,T46

def permute(nums):
    
    def backtrack(path):
        if len(path) == n:
            res.append(path[:])
        for num in nums:
            if not num in path:
                path.append(num)
                backtrack(path)
                path.pop()
        
    n = len(nums)
    res = []
    path = []
    backtrack(path)
    return res
  • 时间复杂度:O(n * n!)
  • 空间复杂度:O(n)

排列有重复不可复选,T47

def permuteWithDup(nums):
    def backtrack(path):
        if len(path) == n:
            res.append(path[:])
            return
        for i in range(n):
            if used[i]:
                continue
            #注意这里添加的not used[i-1],只有前面的相邻相等元素用过了才用这个
            if i > 0 and nums[i] == nums[i - 1] and not used[i-1]:
                continue
            path.append(nums[i])
            used[i] = True
            backtrack(path)
            path.pop()
            used[i] = False

    n = len(nums)
    if n == 0:
        return [[]]
    nums.sort()
    path = []
    res = []
    used = [False] * n
    backtrack(path)
    return res
  • 时间复杂度:O(n * n!)
  • 空间复杂度:O(n)

排列无重复可复选

组合

组合不重复不可复选,T77

题目:1…n中大小为k的组合

def combine(n,k):
	res = []
    path = []
    
    def backtrack(start, k):
        if k == 0:
            res.append(path[:])
        for i in range(start, n + 1):
            path.append(i)
            backtrack(i + 1, k - 1)
            path.pop()
    
    backtrack(1, k)
    return res
  • 时间复杂度:O(k * C(n,k))
  • 空间复杂度:O(n)

组合总和有重复不可复选,T40

def combinesum2(candidates, target):
    def backtrack(start,cursum):
        if cursum == target:
            res.append(path[:])
            return
        if cursum > target:
            return
        for i in range(start, n):
            if i > start and candidates[i] == candidates[i - 1]:
                continue
            path.append(candidates[i])
            backtrack(i + 1, cursum + candidates[i])
            path.pop()

    candidates.sort()
    n = len(candidates)
    res = []
    path = []
    backtrack(0,0)
    return res
  • 时间复杂度:O(n * 2^n)
  • 空间复杂度:O(n)

组合总和无重复可复选,T39

def combinationSum(candidates, target):
    
    def backtrack(start, cursum):
        if cursum == target:
            res.append(path[:])
            return
        if cursum > target:
                return
        for i in range(start, len(candidates)):
            path.append(candidates[i])
            backtrack(i,cursum+candidates[i])
            path.pop()


    res = []
    path = []
    backtrack(0, 0)
    return res
  • 时间复杂度:O(S),S为所有可行解的长度之和
  • 空间复杂度:O(target)+ O(n)

子集

子集不重复不可复选,T78

def subset(nums):
    
    def backtrack(nums, start):
        res.append(path[:])
        for i in range(start+1, n):
            path.append(nums[i])
            backtrack(nums, i + 1)
            path.pop()
    
    n = len(nums)
    path = []
    res = []
    backtrack(nums, 0)
    return res
  • 时间复杂度:O(n * 2^n)
  • 空间复杂度:O(n)

子集有重复不可复选,T90

def subsetWithDup(nums):
    def backtrack(start):
        res.append(path[:])
        for i in range(start, n):
            if i > start and nums[i] == nums[i - 1]:
                continue
            path.append(nums[i])
            backtrack(i + 1)
            path.pop()

    path = []
    res = []
    nums.sort()
    n = len(nums)
    backtrack(0)
    return res
  • 时间复杂度:O(n * 2 ^ n)
  • 空间复杂度:O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值