首页 > 其他分享 >LeetCode【0046】全排列

LeetCode【0046】全排列

时间:2024-11-14 09:19:28浏览次数:3  
标签:排列 递归 nums 交换 0046 回溯 LeetCode first

本文目录

1 中文题目

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

示例:

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

提示:

  • 1 ≤ n u m s . l e n g t h ≤ 6 1 \leq nums.length \leq 6 1≤nums.length≤6
  • − 10 ≤ n u m s [ i ] ≤ 10 -10 \leq nums[i] \leq 10 −10≤nums[i]≤10
  • nums 中的所有整数 互不相同

2 求解方法:回溯法

2.1 方法思路

方法核心

使用回溯法并通过交换元素的方式实现全排列,对于每个位置,将其后面的每个数字(包括自己)都尝试放到当前位置,然后递归处理剩余位置,完成后再将元素换回原位,通过这种方式避免使用额外的标记数组和临时数组,达到空间复杂度的最优。

实现步骤

(1)初始化阶段:

  • 创建结果列表用于存储所有排列
  • 获取输入数组的长度
  • 定义回溯函数,参数为当前待填充的位置

(2)回溯过程:

  • 如果当前位置达到数组末尾,说明找到一个完整排列
  • 将当前位置与其后的每个位置(包括自身)进行交换
  • 递归处理下一个位置
  • 处理完成后将元素换回原位,保持状态不变

(3)状态恢复:

  • 每次递归返回前都要将交换的元素换回原位
  • 确保不影响下一次交换的正确性

(4)结果收集:

  • 当填充完所有位置时,将当前排列加入结果集
  • 注意要创建当前数组的副本

方法示例

以输入 nums = [1,2,3] 为例:

初始状态:
nums = [1,2,3]
result = []

递归过程详解:

1. first = 0:
   1.1 i = 0: 交换nums[0]和nums[0]:[1,2,3]
       递归到first = 1
       1.1.1 i = 1: 交换nums[1]和nums[1]:[1,2,3]
             递归到first = 2
             1.1.1.1 i = 2: 交换nums[2]和nums[2]:[1,2,3]
                   递归到first = 3,添加排列[1,2,3]
             恢复:[1,2,3]
       1.1.2 i = 2: 交换nums[1]和nums[2]:[1,3,2]
             递归到first = 3,添加排列[1,3,2]
             恢复:[1,2,3]
       恢复:[1,2,3]
   
   1.2 i = 1: 交换nums[0]和nums[1]:[2,1,3]
       递归到first = 1
       1.2.1 i = 1: 交换nums[1]和nums[1]:[2,1,3]
             递归到first = 2
             添加排列[2,1,3]
       1.2.2 i = 2: 交换nums[1]和nums[2]:[2,3,1]
             递归到first = 3,添加排列[2,3,1]
             恢复:[2,1,3]
       恢复:[1,2,3]
   
   1.3 i = 2: 交换nums[0]和nums[2]:[3,2,1]
       递归到first = 1
       1.3.1 i = 1: 交换nums[1]和nums[1]:[3,2,1]
             递归到first = 2,添加排列[3,2,1]
       1.3.2 i = 2: 交换nums[1]和nums[2]:[3,1,2]
             递归到first = 3,添加排列[3,1,2]
             恢复:[3,2,1]
       恢复:[1,2,3]

最终结果:
result = [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,2,1], [3,1,2]]

2.2 Python代码

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # 结果列表
        result = []
        n = len(nums)
        
        def backtrack(first = 0):
            # 如果所有数都填完了,将当前排列添加到结果中
            if first == n:
                result.append(nums[:])
                return
            
            # 对当前位置之后的所有数字进行尝试
            for i in range(first, n):
                # 将当前数字交换到待填充的位置
                nums[first], nums[i] = nums[i], nums[first]
                # 递归填充下一个位置
                backtrack(first + 1)
                # 恢复现场,将数字换回原位
                nums[first], nums[i] = nums[i], nums[first]
        
        # 从第一个位置开始回溯
        backtrack()
        return result

2.3 复杂度分析

  • 时间复杂度:O(n!)
    • 回溯树的每个分支都代表一种可能的排列。树的总节点数量就是O(n!)
    • 每个节点的操作(包括交换和可能的复制)都是O(1)级别的
  • 空间复杂度:O(n)
    • 递归调用栈的深度为O(n)
    • 不需要额外的标记数组

3 题目总结

题目难度:中等
数据结构:数组
应用算法:回溯法

标签:排列,递归,nums,交换,0046,回溯,LeetCode,first
From: https://blog.csdn.net/qq_32882309/article/details/143754559

相关文章

  • [LeetCode] 1385. Find the Distance Value Between Two Arrays
    Giventwointegerarraysarr1andarr2,andtheintegerd,returnthedistancevaluebetweenthetwoarrays.Thedistancevalueisdefinedasthenumberofelementsarr1[i]suchthatthereisnotanyelementarr2[j]where|arr1[i]-arr2[j]|<=d.Exampl......
  • LeetCode 3341. Find Minimum Time to Reach Last Room I
    原题链接在这里:https://leetcode.com/problems/find-minimum-time-to-reach-last-room-i/description/题目:Thereisadungeonwith nxm roomsarrangedasagrid.Youaregivena2Darray moveTime ofsize nxm,where moveTime[i][j] representsthe minimum ......
  • 代码随想录算法训练营第二十五天| leetcode491.递增子序列、leetcode46.全排列、leetc
    1leetcode491.递增子序列题目链接:491.非递减子序列-力扣(LeetCode)文章链接:代码随想录视频链接:回溯算法精讲,树层去重与树枝去重|LeetCode:491.递增子序列_哔哩哔哩_bilibili思路:用之前的方法,结果翻车了,好好看视频学新技能吧1.1视频后的思路真的没想到用set来去重,还是基......
  • 代码随想录算法训练营第二十四天| leetcode93.复原IP地址、 leetcode78.子集、leetcod
    1leetcode93.复原IP地址题目链接:93.复原IP地址-力扣(LeetCode)文章链接:代码随想录视频链接:回溯算法如何分割字符串并判断是合法IP?|LeetCode:93.复原IP地址_哔哩哔哩_bilibili思路:就是将这个字符串符合要求的进行一个收集,然后使用列表存储,最后使用join函数将这个列表进行连......
  • LeetCode 69[x的平方根]
    题目链接LeetCode69[x的平方根]详情实例提示题解思路由于所求的是整型且是正符号整型,可以采取循环遍历的方式来求取平方根用for循环将i由0开始遍历,求平方值当平方值小于指定值,此时循环继续直到以下两种情况时退出循环:当平方值为指定值时,返回i 当平方值......
  • leetcode 59. 螺旋矩阵 II java解法
    以123456789为例n=奇数结果1                2                3      i8                9                47                6             ......
  • 代码随想录算法训练营第二十三天| leetcode39. 组合总和、leetcode40.组合总和II、lee
    1leetcode39.组合总和题目链接:39.组合总和-力扣(LeetCode)文章链接:代码随想录视频链接:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)|回溯法精讲!_哔哩哔哩_bilibili思路:跟之前差不多,就是将他的循环改一下,但是我发现有重复的数值了,不知道如何删除1.1自......
  • leetcode 50. Pow(x, n)
    50.Pow(x,n)要特别注意n的范围,如果n=-2^31,使用int是不可以直接n=-n;的 一、使用longclassSolution{public:doublemyPow(doublex,intn){if(x==0)return0;if(n==0)return1;if(n==1)returnx;......
  • Leetcode 148. 排序链表
    给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。经典的分治算法应用,通过归并进行排序,需要用到一个与原数组相同长度的数组归(分割)思想如上图所示,代码实现通过快慢指针来寻找链表的中点来分割指针varspilitList=function(head){if(head===......
  • LeetCode 836[矩形重叠]
    题目链接LeetCode836[矩形重叠]详情实例提示题解思路无重叠的四种情况:第二个矩形的右边边如果在第一个矩形的左边边的左边或重叠第二个矩形的左边边如果在第一个矩形的右边边的右边或重叠第二个矩形的上边边如果在第一个矩形的下边边的下边或重叠第二个矩形的下......