Leetcode46:全排列问题(回溯算法)

这篇博客详细介绍了如何解决LeetCode第46题——全排列问题,通过两种不同的回溯算法实现。第一种解法使用了二维数组res存储结果,LinkedList作为临时路径,并使用一个布尔数组used记录元素使用状态。第二种解法同样采用回溯,通过跟踪当前路径track和使用状态used,递归寻找所有可能的排列。在递归过程中,每次选择一个未使用的元素,并在回溯时撤销选择,确保不会重复添加相同的排列。
摘要由CSDN通过智能技术生成

Leetcode46:全排列问题

解法一:(推荐)

  • 题目:
    • 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
  • 思路:回溯算法+代码注释
  • 代码如下:
class Solution {
    //定义二维数组存放结果集
    List<List<Integer>> res = new ArrayList<>();
    //定义一维数组存放临时路径
    LinkedList<Integer> path = new LinkedList<>();
    //定义一维数组used用于判断数组nums中的元素是否被使用过
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        if ( nums.length == 0 ) {
            res.add( new ArrayList<>(path) );
            return res;
        }
        used = new boolean[nums.length];
        //回溯算法(全排列问题,不增加startIndex)
        backtarck(nums);
        return res;
    }
    void backtarck(int[] nums){
        //当临时路径path长度跟数组nums长度相同时,说明path已经符合要求,加入二维数组res结果集
        if ( nums.length == path.size()){
            res.add( new ArrayList<>(path) );
            return;
        }
        //全排列问题(从0开始遍历)
        for ( int i = 0; i < nums.length; i++ ) {
            if ( used[i] ) {
                continue;
            }
            used[i] = true;
            path.add(nums[i]);
            backtarck(nums);
            path.remove(path.size()-1);
            used[i] = false;
        }
    }
}

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

  • 回溯算法的核心是 for 循环里面的递归,在递归调用之前[做选择],在递归调用之后[撤销选择]
class Solution {
    List<List<Integer>> res = new LinkedList<>();
    //结果返回的是一个二维列表,提前定义为全局变量,后面的回溯方法backtrack()会用到

    public List<List<Integer>> permute(int[] nums) {
        LinkedList<Integer> track = new LinkedList<>();
        boolean[] used = new boolean[nums.length];

        backtrack(nums,track,used);
        return res;

    }
    public void backtrack(int[] nums,LinkedList<Integer> track,boolean[] used){
            //当列表的长度达到数组的长度时,说明列表的元素已经达到要求,直接添加到二维列表成为元素
            if(track.size()==nums.length){
                res.add(new LinkedList(track));
                return;
                //核心在于此处的return,使二维列表每添加一个一维列表之后,j重新开始
            }
            for(int i=0;i<nums.length;i++){
				//如果used[i]为真,说明该元素已经被添加到列表,直接continue进行循环
                if(used[i]){
                    continue;
                }
                //说明该元素未被添加到列表,添加至列表,然后设置used[i]为真,防止重复添加相同元素
                track.add(nums[i]);
                used[i]=true;
                backtrack(nums,track,used);
                //当退出循环时,说明列表tarck的长度已经达到要求,此时依次将tarck列表的元素移除,				    //并重新设置used[i]为false
                track.removeLast();
                used[i]=false;


            }

        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值