题目
给定一个不含重复数字的数组 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]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法1
回溯,好像悟了一点点。
1、注意:
res.add(new LinkedList(track));
标注:如果res.add(new LinkedList(track)),不用新变量做拷贝的话,写成res.add(track)的话,最后得到的会是全部为空的列表。
原因:变量 track所指向的列表 在深度优先遍历的过程中只有一份 ,深度优先遍历完成以后,回到了根结点,成为空列表。
在 Java 中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到 res 变量,但实际上指向的是同一块内存地址,因此我们会看到 6 个空的列表对象。
2、track 用 LinkedList 声明,是因为要用 removeLast() 方法
Java实现1
class Solution {
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
//选择列表 track
LinkedList<Integer> track = new LinkedList<>();
backtrack(nums, track);
return res;
}
public void backtrack(int[] nums, LinkedList<Integer> track){
//结束条件:nums中的元素都在track里
if (track.size() == nums.length){
res.add(new LinkedList(track));
return;
}
//
for (int i = 0; i < nums.length; i++){
//⭐:排除不合法的选择
if (track.contains(nums[i])) continue;
//做选择
track.add(nums[i]);
//进入下一层决策树
backtrack(nums, track);
//取消选择
track.removeLast();
}
}
}
Java实现2
class Solution {
List<List<Integer>> res = new ArrayList<>();
//⭐used 数组来标记哪些元素还可以被选择
boolean[] visited;
int n;
public List<List<Integer>> permute(int[] nums) {
n = nums.length;
visited = new boolean[n];
LinkedList<Integer> track = new LinkedList<>();
track_back(nums, track);
return res;
}
public void track_back(int[] nums, LinkedList<Integer> track) {
if (track.size() == n) {
res.add(new ArrayList<>(track));
return;
}
for (int i = 0; i < n; i++) {
if (visited[i]) continue;
track.add(nums[i]);
visited[i] = true;
track_back(nums, track);
visited[i] = false;
track.removeLast();
}
}
}