13.1 全排列(46)
图片
思路
当第一个数选1 时
|
第二层 的数 只能选2,3
|
第二层选2时,第三层只能选3;当第二层选3时,第三层只能选2
定义一个List<List<Integer>> res,集合元素为 Integer类型的集合 的集合res。来存储每一种排列方式[[1,2,3],[1,3,2]]
定义一个List<Integer> track,集合元素为Integer类型,用来存储一种排列方式 [1,2,3]
每当找到一种排列方式时,需要往 上一层 回退 ,操作的方法就是 删掉track中最后一个元素 使用递归调用时,当函数执行完成,就会回到上一层的递归,利用这一特点,将 删除集合最后一个元素这个操作,定义为函数的最后一步。这样上一层函数的track就保持不变
具体例子:
第二层track(1,2) 执行递归 进第三层
第三层执行循环 1,2都存在于track中,将3加入track track(1,2,3) 此时删掉3 track(1,2)
返回上一层函数调用,第二层的track(1,2)未变化
当track的数量 与 传入的数组nums 长度相同时,说明 找到了一种全排列,加入res中,此时返回上一层
具体例子:
当1,3,2这种排列被找到并加入res后,此时回到第二层 track(1,3,2) -> track(1,3)
此时for循环还要执行一轮 i = 2 nums[2] = 3
判断track中是否有3 发现track中存在3 进入下一轮循环
解法
class Solution {
//定义集合 用来存放所有全排列情况
List<List<Integer>> res = new ArrayList<>();
//执行操作后 返回上文定义的集合
public List<List<Integer>> permute(int[] nums) {
List<Integer> track = new ArrayList<>();
method(nums,track);
return res;
}
public void method(int[] nums,List<Integer> track){
//当集合元素数 = 数组元素数 时 说明 完成了一种全排列情况 加入到res中 然后 返回上一层method函数
if(track.size() == nums.length){
//注意:集合是引用类型,需要new一个新的集合,否则最后放入的每一个track均为空集合(递归调用结束,track中无元素)
res.add(new ArrayList<>(track));
return;
}
//循环用来 选择元素 放入track集合中
for(int i = 0;i<nums.length;i++){
//集合中存在该元素时 进入下一轮循环
if(track.contains(nums[i])){
continue;
}
track.add(nums[i]);
//递归 进入下一层 选择
method(nums,track);
//执行到这句话时 说明一种全排列已经发现,此时要回到上一层函数 就需要去掉集合中最后一个元素
track.remove(track.size()-1);
}
}
}