LeetCode全排列 回溯与递归

46. 全排列

给定一个不含重复数字的数组 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]]

思路:

  直接说方法,就是回溯+递归!可以参考39. 组合总和

  我们同样想象一棵选择树,对于数组[1,2,3]一开始抓取,可以抓1或2或3——说明我们依然要通过回溯的方式来尝试所有的选择。

  我们定义递归函数,同样是有两个参数(has, choose),但因为这一题是不放回的抓取,所以我们每次递归时,需要判断当前选择是否已经选了,已经有了则跳过。当现有has长度等于给定选择列表时,我们就存入结果。

  最后老生常谈的是:每次送入递归之后要马上退回当前状态,这就是经典回溯了。

代码:

class Solution(object):

    def permute(self, nums):

        res=[] #存储结果的列表

        lenth = len(nums)

        def di(has,choose):

            if len(has)==lenth:#base case上来写

                res.append(has[:])#重点1 放的是个copy切片

            for cho in choose:

                if cho not in has:#重点2判断has是否已有这个选择

                    has.append(cho)#若没有 加入这个选择

                    di(has,choose)#送入递归

                    has.pop()#恢复状态

        di([],nums)#开始has为空,选择列表为nums

        return res

小结:

  总之这个题是很基础的了,基本上回溯相关的问题我都是采用类似的像模板一样去做的。

  这里有个小坑,我们存入res结果的列表,要是切片,因为切片是额外复制出的一份,假如不是切片,则后面会被莫名其妙地修改!你自己都找不到原因。所以这里要特别注意!

  原本对于“不放回”的回溯,我们是要每次更新选择列表的,但那样操作起来麻烦很大。因此直接每次选择时来判断是否已经选了,通过这种方式来避免重复选择,就容易实现多了。

posted @   JunanP  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 我与微信审核的“相爱相杀”看个人小程序副业
· DeepSeek “源神”启动!「GitHub 热点速览」
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示