题目
给定一个不含重复数字的数组 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
中的所有整数 互不相同
解析
这道题目是一道回溯算法问题,需要枚举出所有可能的情况。
回溯法:一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试。
深度优先搜索 算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会 尽可能深 的搜索树的分支。当结点 v 的所在边都己被探寻过,搜索将 回溯 到发现结点 v 的那条边的起始结点。这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点,则选择其中一个作为源结点并重复以上过程,整个进程反复进行直到所有结点都被访问为止。
基本逻辑
题目让我们返回一个List,我们需要定义res数组来作为返回的结果,另外需要定义一个List数组 path 作为res中的元素。我们利用Path来保证数组不重复。
在traverse,我们进行代码逻辑的书写。首先我们先遍历数组,
java
for(int i = 0;i < nums.length;i++){
if(path.contains(nums[i])){
continue;
}else{
path.add(nums[i]);
traverse(nums);
path.remove(path.size()-1);
}
}
这里的逻辑是,如果当前的数字已经在Path中之后,那么我们就跳过这个数字。如果不在的话,那么我们在以这个数字为根节点去递归。注意,如果数字不在这个Path中,我们进入else条件之中,要写上 path.add(nums[i]); 并且当我们递归结束,返回到这一层递归时,要把当前数字移除path中,来进行所有数字的枚举。
变量 path 所指向的列表 在深度优先遍历的过程中只有一份 ,深度优先遍历完成以后,回到了根结点,成为空列表。
问题
出现六个空列表
在 Java 中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到 res 变量,但实际上指向的是同一块内存地址,因此我们会看到 666 个空的列表对象。解决的方法很简单,在 res.add(path); 这里做一次拷贝即可。
修改的部分:
java
if(path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
此时再提交到「力扣」上就能得到通过了。
代码
java
class Solution {
//使path和res每次不跟着刷新
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
traverse(nums);
return res;
}
void traverse(int[] nums){
if(path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
for(int i = 0;i < nums.length;i++){
if(path.contains(nums[i])){
continue;
}else{
path.add(nums[i]);
traverse(nums);
path.remove(path.size()-1);
}
}
}
}