LeetCode100之全排列(46)--Java

1.问题描述

给定一个不含重复数字的数组 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 中的所有整数 互不相同

难度等级

中等

题目链接

全排列

2.解题思路

这道题要求我们返回所有可能的全排列,每一个数都有可能在每一个位置出现,这里我们要用到回溯的思想。

在解题之前,我们要先来定义一些变量,我们的一个排列,可以用一个List集合来表示,我们可以用一个辅助的List集合来寻找所有的全排列,并定义一个用来存储最终所有全排列的List数组(data),接着,我们还需要一个标识数组,来标识nums中的哪些数已经在当前排列中出现过了,防止出现同一个nums[i],在一个排列中排了两次。

java 复制代码
        List<List<Integer>> data = new ArrayList<>();
        boolean[] used = new boolean[nums.length];

这道题我们可以编写一个递归+回溯的方法来找到所有的排列。

递归的结束条件是当辅助List的个数等于nums数组的个数时,说明所有的数都已经拿出来进行排列了,已经得到一个新的排列,这时,创建一个新的List将辅助数组的元素存入新的List中,再将List存入最终用来存储所有全排列的List集合中,然后直接返回即可。

java 复制代码
        //如果list的大小 = nums的个数,说明得到一个排列
        if(list.size() == nums.length){
            //添加新的排列
            data.add(new ArrayList<>(list));
            return;
        }

正常的递归逻辑也很简单,用一个for循环对nums数组进行遍历,先判断当前的数是否已经在辅助List排列了,如果已经在List中排列,则跳过这一个数。

java 复制代码
        //遍历nums数组,将还没排列的数字取出来进行排序
        for(int i = 0;i < nums.length;i++){
            //已经被用过的数,直接跳过
            if(used[i] == true){
                continue;
            }
            ......
         }

如果还没有在参与排列,则将标记改为true并添加到辅助List中,参与排列,接着递归调用当前方法继续进行查找。找到包含当前子排列的所有排列之后,我们还需要对当前的排列进行回溯,将标记重新改回false,并将当前对应的这个数从辅助list中取出,防止对后面的排列造成影响。

java 复制代码
        //遍历nums数组,将还没排列的数字取出来进行排序
        for(int i = 0;i < nums.length;i++){
            ......
            //标记为已使用
            used[i] = true;
            //添加到当前的排列中
            list.add(nums[i]);
            //递归
            backtrack(data,list,nums,used);
            //回溯
            list.remove(list.size()-1);
            used[i] = false;
        }

当递归方法完全执行完成之后,直接将用来存储全排列的List集合(data)返回即可。

java 复制代码
        backtrack(data,new ArrayList<Integer>(),nums,used);
        return data;

3.代码展示

java 复制代码
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> data = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        backtrack(data,new ArrayList<Integer>(),nums,used);
        return data;
    }
    public void backtrack(List<List<Integer>> data,List<Integer> list,int[] nums,boolean[] used){
        //如果list的大小 = nums的个数,说明得到一个排列
        if(list.size() == nums.length){
            //添加新的排列
            data.add(new ArrayList<>(list));
            return;
        }
        //遍历nums数组,将还没排列的数字取出来进行排序
        for(int i = 0;i < nums.length;i++){
            //已经被用过的数,直接跳过
            if(used[i] == true){
                continue;
            }
            //标记为已使用
            used[i] = true;
            //添加到当前的排列中
            list.add(nums[i]);
            //递归
            backtrack(data,list,nums,used);
            //回溯
            list.remove(list.size()-1);
            used[i] = false;
        }
    }
}

4.总结

这道题没什么太大的难度,采用回溯+递归的方法穷尽所有的排列可能,让每一个数在每一个位置都出现一次。好了,这道题没啥好啰嗦的,祝大家刷题愉快,早日上岸!

相关推荐
故事和你911 小时前
洛谷-数据结构1-1-线性表1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
脱氧核糖核酸__1 小时前
LeetCode热题100——53.最大子数组和(题解+答案+要点)
数据结构·c++·算法·leetcode
脱氧核糖核酸__2 小时前
LeetCode 热题100——42.接雨水(题目+题解+答案)
数据结构·c++·算法·leetcode
一 乐2 小时前
电影院|基于springboot + vue电影院购票管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·电影院购票管理管理系统
恼书:-(空寄2 小时前
JVM GC 日志分析 + 常见 GC 场景 + 实战参数调优
java·jvm
消失的旧时光-19432 小时前
Spring Boot 实战(五):接口工程化升级(统一返回 + 异常处理 + 错误码体系 + 异常流转机制)
java·spring boot·后端·解耦
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I
c++·算法·编程·贪心·csp·信奥赛·线性扫描贪心
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:分糖果
c++·算法·贪心算法·csp·信奥赛·线性扫描贪心·分糖果
_日拱一卒3 小时前
LeetCode:2两数相加
算法·leetcode·职场和发展
py有趣3 小时前
力扣热门100题之零钱兑换
算法·leetcode