力扣 46. 全排列(dfs入门第一题)

题目

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

样例

示例 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 中的所有整数 互不相同

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目解析

这是第三次写全排列了吧,每一次都以为自己会了。看了解析再写和自己一行行思考是完全不一样的,一想就是一个半小时,这大概就是真的会了吧。

Q1:需要想清楚,dfs的终止条件是什么?

A:加入输入是3个数,那么终止条件为我找全了3个数,就可以保存了。

Q2:如何知道一个数字有没有取过?

A:每个数字只能出现一遍,因此用一个访问数组vis记录每个数字是否访问过。如果输入为3个数,那么vis = [0, 0, 0]表示这三个数都没有访问过,如果访问了标记为0.

Q3:如何开始搜索

A:遍历每一个数,看看是否用过,用过的数就不再用了,继续查看下一个数。当找到没用过的数时,进入下一步dfs继续对下一个位置进行搜索。

Q4:如何进行回溯

A:每个位置dfs结束后,需要退还用过的数值,恢复vis[]标记到0

Q5:困扰的变量联动?

A:当res变量被修改时,resAll变量的值会随之修改,这里的解决方法是用切片,resAll.append(res[:]),将res的所有值切片取出来存入resAll,就可以了,当然也可以用别的方法,比如说copy,这里切片可能对初学者更友好。

本地编译器写的代码

nums = [1, 2, 3]
n = len(nums)
resAll = []
vis = [0 for i in range(n + 1)]

def dfs(step, res):
    global resAll
    if step > n:
        resAll.append(res[:])
        return

    # 继续搜索
    for i in range(n):  # 0, 1, 2
        if vis[i] == 0:
            vis[i] = 1
            res.append(nums[i])
            dfs(step + 1, res)
            res.pop()
            vis[i] = 0

res = []
dfs(1, res)
print(resAll)

力扣提交的代码

力扣里面的变量不需要全局变量申明,可以直接使用。其他和本地的代码没有什么区别啦!

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        resAll = []
        vis = [0 for i in range(n + 1)]

        def dfs(step, res):
            
            if step > n:
                resAll.append(res[:])
                return

            # 继续搜索
            for i in range(n):  # 0, 1, 2
                if vis[i] == 0:
                    vis[i] = 1
                    res.append(nums[i])
                    dfs(step + 1, res)
                    res.pop()
                    vis[i] = 0

        res = []
        dfs(1, res)
        return resAll

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值