这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
最近被工作上的一些事情搞得焦头烂额,也有段时间每继续每天做题了。持续做一件事情,每天都能坚持,特别难,中途放弃又特别容易。但是正是因为这样,坚持下来的成就感才足够大吧。往昔不可追,做好当下才最重要。种一棵树最好的时机是十年前,其次是现在。
题目
给定一个不含重复数字的数组
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]]
思路
先想象一下,如果这个题目给你,人工会怎么做。
大致应该是:先获取位数,然后每一位都嵌套一层for循环,循环数组中的每个数字,但是有个条件是,外层for循环当前正在使用的数字,在里层的for循环就不能再使用了。
其实里层for循环到外层for循环的过程,就是回溯的过程。每次最先改变的是最里层for循环的值,这是对上一次结果的最小改变,慢慢的,再开始走外层的for循环,就是每次只改变一点点,慢慢试探,但是这个过程要做到不重不漏。下图就是示例1按照这个步骤的过程:
我们现在就是要用代码来实现这一个过程,但是上面的思路中,数字的个数就是for循环的个数,直接是没法写的,因为数组的长度是变化的,只能写一个for循环,然后递归调用,递归的次数就是for循环的次数,即数组的长度。
Java版本代码
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> item = new ArrayList<>();
int len = nums.length;
boolean[] used = new boolean[len];
dfs46(result, item, nums, 0, used);
return result;
}
private static void dfs46(List<List<Integer>> result, List<Integer> item, int[] nums, int depth, boolean[] used) {
int len = nums.length;
if (depth == len) {
result.add(new ArrayList<>(item));
return;
}
for (int i = 0; i < len; i++) {
if (!used[i]) {
item.add(nums[i]);
used[i] = true;
dfs46(result, item, nums, depth + 1, used);
used[i] = false;
item.remove(item.size() - 1);
}
}
}
}