Leetcode46:全排列问题
解法一:(推荐)
- 题目:
- 给定一个不含重复数字的数组
nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
- 给定一个不含重复数字的数组
- 思路:回溯算法+代码注释
- 代码如下:
class Solution {
//定义二维数组存放结果集
List<List<Integer>> res = new ArrayList<>();
//定义一维数组存放临时路径
LinkedList<Integer> path = new LinkedList<>();
//定义一维数组used用于判断数组nums中的元素是否被使用过
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
if ( nums.length == 0 ) {
res.add( new ArrayList<>(path) );
return res;
}
used = new boolean[nums.length];
//回溯算法(全排列问题,不增加startIndex)
backtarck(nums);
return res;
}
void backtarck(int[] nums){
//当临时路径path长度跟数组nums长度相同时,说明path已经符合要求,加入二维数组res结果集
if ( nums.length == path.size()){
res.add( new ArrayList<>(path) );
return;
}
//全排列问题(从0开始遍历)
for ( int i = 0; i < nums.length; i++ ) {
if ( used[i] ) {
continue;
}
used[i] = true;
path.add(nums[i]);
backtarck(nums);
path.remove(path.size()-1);
used[i] = false;
}
}
}
解法二:
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
- 回溯算法的核心是 for 循环里面的递归,在递归调用之前[做选择],在递归调用之后[撤销选择]
class Solution {
List<List<Integer>> res = new LinkedList<>();
//结果返回的是一个二维列表,提前定义为全局变量,后面的回溯方法backtrack()会用到
public List<List<Integer>> permute(int[] nums) {
LinkedList<Integer> track = new LinkedList<>();
boolean[] used = new boolean[nums.length];
backtrack(nums,track,used);
return res;
}
public void backtrack(int[] nums,LinkedList<Integer> track,boolean[] used){
//当列表的长度达到数组的长度时,说明列表的元素已经达到要求,直接添加到二维列表成为元素
if(track.size()==nums.length){
res.add(new LinkedList(track));
return;
//核心在于此处的return,使二维列表每添加一个一维列表之后,j重新开始
}
for(int i=0;i<nums.length;i++){
//如果used[i]为真,说明该元素已经被添加到列表,直接continue进行循环
if(used[i]){
continue;
}
//说明该元素未被添加到列表,添加至列表,然后设置used[i]为真,防止重复添加相同元素
track.add(nums[i]);
used[i]=true;
backtrack(nums,track,used);
//当退出循环时,说明列表tarck的长度已经达到要求,此时依次将tarck列表的元素移除, //并重新设置used[i]为false
track.removeLast();
used[i]=false;
}
}
}