leetcode【中等】46、全排列

在这里插入图片描述
思路:回溯
遍历数组,遇到一个数没被用过,就添加到路径里,接着向下搜索;
当搜索深度depth等于数组大小,结束,把路径添加到结果里

设置数组 used记录每个数字是否被选过,初始化的时候都为 false ,当我们选定一个数的时候,就将这个数组的相应位置设置为 true

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(depth,used):
            if depth==l:
                res.append(path[:])
                return
            for i in range(l):
                if not used[i]:
                    used[i]=True
                    path.append(nums[i])

                    dfs(depth+1,used)                    
					#回撤操作
                    used[i]=False
                    path.pop()
        l=len(nums)
        used = [False for _ in range(l)]
        res=[]
        path=[]
        dfs(0,used)
        return res

优化空间:不使用额外空间used数组记录状态

将题目给定的 n 个数的数组nums[] 划分成左右两个部分,左边的表示已经填过的数,右边表示待填的数,我们在递归搜索的时候只要动态维护这个数组即可。

具体来说,假设我们已经填到第depth 个位置,那么 nums[] 数组中[0,depth−1] 是已填过的数的集合,[depth,n−1] 是待填的数的集合。

我们肯定是尝试用[depth,n−1] 里的索引为i的数去填第depth个数,那么填完以后我们将第 i 个数和第 depth个数交换,即可满足要求,回溯的时候交换回来即能完成撤销操作。

那么一个数组目前为 [8, 9 | 2, 5, 10] 这样的状态,分隔符区分了左右两个部分。假设这个位置我们要填 10 这个数,为了维护数组,我们将 2 和 10 交换,变为 [8, 9, 10 | 2, 5] 。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(depth):
            if depth == l:
                # 所有数都填完了
                res.append(nums[:])
            for i in range(depth, l):
                nums[i], nums[depth] = nums[depth], nums[i]
                dfs(depth + 1)
                # 撤销操作
                nums[i], nums[depth] = nums[depth], nums[i]

        l=len(nums)
        res=[]
        dfs(0)
        return res

猜你喜欢

转载自blog.csdn.net/qq_40707462/article/details/113567539