回溯的问题合集(Leetcode题解-Python语言)

78. 子集
在这里插入图片描述

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        ans = []
        cur = []

        def dfs(i):
            if i == len(nums):
                ans.append(cur.copy())
                return
            
            # 包括 nums[i]
            cur.append(nums[i])
            dfs(i+1)
            # 不包括 nums[i]
            cur.pop()
            dfs(i+1)

        dfs(0)
        return ans

要找出所有子集,对于数组里的每个元素,都只有选或不选两种情况,所以从下标 i = 0 开始,包括或不包括 nums[i],然后对下一个位置 i + 1 进行同样操作。由于 cur 数组是会变的,所以要 copy 或者 cur[:]

77. 组合
在这里插入图片描述

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        ans = []
        cur = []

        def dfs(start):
            if len(cur) == k:
                ans.append(cur.copy())
                return
            if start > n:
                return
            
            for i in range(start, n + 1):
                cur.append(i)
                dfs(i + 1)
                cur.pop()
        
        dfs(1)
        return ans

对于组合,考虑了数字 i,后面添加的数要大于 i

39. 组合总和
在这里插入图片描述

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        ans = []
        cur = []

        def dfs(i, total):
            if total == target:
                ans.append(cur.copy())
                return
            if i >= len(candidates) or total > target:
                return
            
            cur.append(candidates[i])
            dfs(i, total + candidates[i])
            cur.pop()
            dfs(i + 1, total)
        
        dfs(0, 0)
        return ans

46. 全排列
在这里插入图片描述

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        ans = []
        cur = []
        counter = collections.Counter(nums)

        def dfs():
            if len(cur) == len(nums):
                ans.append(cur.copy())
                return
            
            for i in counter:
                if counter[i] > 0:
                    cur.append(i)
                    counter[i] -= 1

                    dfs()

                    cur.pop()
                    counter[i] += 1

        dfs()
        return ans

排列从思路上是逐个添加,但是代码实现上要用逐个排除的方法。

90. 子集 II
在这里插入图片描述

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        ans = []
        cur = []
        nums.sort()

        def dfs(i):
            if i == len(nums):
                ans.append(cur.copy())
                return

            cur.append(nums[i])
            dfs(i+1)
            cur.pop()
            while i + 1 < len(nums) and nums[i] == nums[i + 1]:
                i += 1
            dfs(i+1)

        dfs(0)
        return ans

40. 组合总和 II

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        ans = []
        cur = []

        def dfs(pos, total):
            if total == target:
                ans.append(cur.copy())
                return
            if pos >= len(candidates) or total > target:
                return
            
            pre = -1
            for i in range(pos, len(candidates)):
                if candidates[i] == pre:
                    continue
                cur.append(candidates[i])
                dfs(i + 1, total + candidates[i])
                cur.pop()
                pre = candidates[i]
            
                
        dfs(0, 0)
        return ans

47. 全排列 II

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        ans = []
        cur = []
        counter = collections.Counter(nums)

        def dfs():
            if len(cur) == len(nums):
                ans.append(cur.copy())
                return
            
            for i in counter:
                if counter[i] > 0:
                    cur.append(i)
                    counter[i] -= 1

                    dfs()

                    cur.pop()
                    counter[i] += 1

        dfs()
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值