Leetcode 46 全排列 簡單思路以及解法

Leetcode 46 全排列 簡單思路以及解法

題目以下:數組

給定一個沒有重複數字的序列,返回其全部可能的全排列。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;
    }
}
相關文章
相關標籤/搜索