(回溯算法)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]]

提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同

思路

首先,选择路径‌:开始点都是当前数组所有的下标

其次,递归探索‌:在上一步中,选择的开始下标 start 之前的所有下标是不变化的,但是后面剩下的下标 又需要 重复 上一步的路径选择 和 这一步的 递归探索

然后,确定终止条件‌:在上一步 递归的过程 中,我们设 当前已经确定的位置为start(即从左到start是已经确定好的),所以终止条件是 start==nums.length,便说明截止到当前,此种情况的排列已经排好了

最后,回退与恢复‌:在上面的操作中,我们发现如果使用很多new的集合的话,会导致空间消耗,所以,回溯最好是在排列好的集合加入后从操作,即:撤销这一个位置填的数以及标记(start),并继续尝试其他没被标记过的数(因为使用的是一个集合,加入已排列好的集合是在回溯前new的新集合,因此必须回退之前的操作)

可以查看一下这个LeetCode上的图
在这里插入图片描述

算法

class Solution {
    List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> permute(int[] nums) {
        int length = nums.length;
        List<Integer> list = new ArrayList<>();
        for(int num : nums) {
            list.add(num);
        }
        backtrack(0, length, list);
    
        return res;
    }

    void backtrack(int start, int end, List<Integer> list) {
        if (start == end) {
            res.add(new ArrayList<>(list));
        }
        for (int i = start; i < end; ++i) {
            swapList(list, start, i);
            backtrack(start + 1, end, list);
            // 回退list这个集合
            swapList(list, start, i);
        }
    }

    void swapList(List<Integer> list, int index1, int index2) {
        int temp = list.get(index1);
        list.set(index1, list.get(index2));
        list.set(index2, temp);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

?abc!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值