题目以下:数组
给定一个没有重复数字的序列,返回其全部可能的全排列。code
示例:对象
输入: [1,2,3]递归
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]rem
思路:it
拿到题目的时候,看到示例输出,就想着试下回溯解法,采用一个全局的 boolean 数组标识数组中哪些元素被访问过了,递归地产生解集。代码以下:io
class Solution { List<List<Integer>> res;// 存放结果的对象 public List<List<Integer>> permute(int[] nums) { res = new ArrayList<List<Integer>>(); DFS(nums,initializeBooleanArray(nums.length),new ArrayList<Integer>());// 收集全排列的全部排列结果 return res; } // 循环选择固定哪个数字(选择哪个做为起始数字) public void DFS(int[] nums,boolean[] visited,List<Integer> tmp){ // 若是tmp中存放的数字已经将全部nums中的数字都放入了,那么就将其输入到res中 if(tmp.size()==nums.length) res.add(new ArrayList<Integer>(tmp)); else{ // 不然,开始循环遍历,按照0,1,2..的顺序依次选择起点,而后遍历 for(int i=0;i<nums.length;i++){ if(visited[i])// 若该点已经被访问过了,则跳过访问下一个点 continue; else{// 若没被访问过,那么先标记为访问了,而后将其加入tmp中,等待tmp长度足够时写入res中 visited[i] = true; tmp.add(nums[i]); DFS(nums,visited,tmp);// 递归调用,经过形参维护的 逻辑栈的变量有:tmp,visited tmp.remove(tmp.size()-1);// 递归结束,还原该点的状态,使得获取下一个组合的遍历还能再通过此点 visited[i]=false;// 访问标记还原 } } } } // 获取一个与num相等大小的boolean数组 public boolean[] initializeBooleanArray(int num){ boolean[] res = new boolean[num]; for(int i=0;i<num;i++){ res[i] = false; } return res; } }
顺便看了下网上的dalao们的解法,发现有个比较热的解法是交换解法,每次将数与后面的一位进行交换。当交换到最后一位的时候,就将此时的解算入解集中。class
代码以下:变量
public class Solution { List<List<Integer>> res; public List<List<Integer>> permute(int[] nums) { res = new LinkedList<List<Integer>>(); helper(nums, 0); return res; } public void helper(int[] nums, int i){ // 找到转置完成后的解,将其存入列表中 if(i == nums.length - 1){ List<Integer> list = new LinkedList<Integer>(); for(int j = 0; j < nums.length; j++){ list.add(nums[j]); } res.add(list); } // 将当前位置的数跟后面的数交换,并搜索解 for(int j = i; j < nums.length; j++){ swap(nums, i , j); helper(nums, i + 1); swap(nums, i, j); } } private void swap(int[] nums, int i, int j){ int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }