Leetcode 2-25

## 46. 全排列

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

状态树法

这道题目中状态树做法和深搜做法是一模一样的

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        s = [False] * n  # 用于标记是否已使用过该位置的数
        path = []  # 当前构建的排列
        ans = []  # 存储所有的排列

        def dfs(iterator):
            if iterator == n:  # 完成一次排列
                ans.append(path.copy())  # 将当前排列加入到结果集中
                return
            
            for i in range(n):
                if not s[i]:  # 如果第i个数还没有被使用
                    s[i] = True  # 标记为已使用
                    path.append(nums[i])  # 将该数添加到当前排列
                    
                    dfs(iterator + 1)  # 递归调用以处理下一个位置
                    
                    {{path.pop()  # 回溯,撤销上一步的选择}}
                    s[i] = False  # 取消对该数的使用标记

        dfs(0)
        return ans

深度搜索法

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        ans = []
        path = []
        used = [False for _ in range(n)]

        def dfs(iterator):
            if iterator == n:
                ans.append(path.copy())                
                return 

            for i in range(n):
                if not used[i]:
                    used[i] = True
                    path.append(nums[i])
                    dfs(iterator+1)
                    path.pop()
                    used[i] = False

        dfs(0)
        return ans

77. 组合

给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        if n == 0 or k > n:
            return []
        elif n == k:
            return [list(range(1,n+1))]
        
        # 回溯函数(组合类型)
        # params:待挑选数组长度
        # params:每个组合需要的数组长度
        # params:待挑选的数组开始索引(即迭代器iterator,用迭代器普适性更强)
        # params:挑选过程中的路径path
        def backtracking(n,k,begin,path):
            if len(path) == k:
                ans.append(path.copy())
                return

            for i in range(begin,n+1):
                path.append(i)
                # 注意传递的是i+1,而不是begin+1
                # 意思就是从当前挑选的数往后挑选,不会回头看
                # begin表示的不是当前的数,而是这一轮dfs开始的数
                backtracking(n,k,i+1,path)
                path.pop()

        ans = []
        backtracking(n,k,1,[])

        return ans

78. 子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums 中的所有元素 互不相同
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 每次选择拿不拿,迭代器一直往前走,迭代器结束时将path加入ans并return
        ans = []
        path = []

        # 回溯函数(子集类型)
        # params:待挑选的集合
        # params:迭代器iterator
        # params:挑选过程中的路径path
        def backtracking(nums,iterator,path):
            # 当iterator到底时加入path
            if iterator == len(nums):
                ans.append(path.copy())
                return

            # 加入当前iterator的数
            path.append(nums[iterator])
            backtracking(nums,iterator+1,path)
            path.pop()
            # backtracking(nums,iterator+1,path+[nums[iterator]])
            # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>此处为一个右值副本,不是左值所以不是按引用传递

            # 不加入当前iterator的数
            backtracking(nums,iterator+1,path)
            # >>>>>>>>>>>>>>>>>>>>>>>>>>>这里是左值,所以是按引用传递

        backtracking(nums,0,[])

        return ans

90. 子集 II

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        # 首先进行排序获得以便利用顺序特性:该题中的特性为,按顺序来取的话子集中也只会是按顺序排列,那么元组就会自动过滤相同的子集,如果不排序,cnt相同的元组可能会因为顺序不同不能过滤掉,所以要先进行排列
        nums.sort()

        # 该题与子集I的不同点就在于需要去重:
        # 1.利用set过滤不同的元组(之所以是元组(tuple)是因为列表(list)不具有hash性不能加入set)
        # 2.利用排序过滤cnt相同而顺序不同的数组
        ans_set = set()
        path = []

        def backtracking(nums, iterator, path):
            if iterator == len(nums):
                ans_set.add(tuple(path))
                return

            backtracking(nums,iterator+1,path)
            backtracking(nums,iterator+1,path+[nums[iterator]])

        backtracking(nums,0,[])
        return list(ans_set)
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值