題目以下:數組
給定一個沒有重複數字的序列,返回其全部可能的全排列。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; } }