1. 程式人生 > >LeetCode--46. Permutations

LeetCode--46. Permutations

題目連結:https://leetcode.com/problems/permutations/

昨天是組合的題目,今天是排列問題,排列的題目就是對於每個元素在某個特定位置上到底選不選的問題。而在前面的位置上選了的某個元素在後面的位置上是不能選的。這時就需要一個全域性陣列visited來記錄選了的與沒選的情況。與組合一樣,我會用一個ret來儲存所有符合條件的排列情況最終返回,而用record陣列記錄某個符合條件的排列情況(因為每種排列情況的選擇次數是固定的)。比如在第i個位置上我選了待選陣列中第j個元素,那麼在第i+1,i+2,....的位置上就不能再選第j個元素;在第i個位置上我沒選待選陣列中第j個元素,那麼在第i+1,i+2,....的位置上就可以再選第j個元素了。噹噹前一個選擇的後續選擇都做完時(遞迴函式層層深入),跳出當前的遞迴函式時需要將該位置上選擇記錄給復位。

具體步驟如圖:藍色標記表示選擇該位置上的數字,選完後在後續步驟中就不能選了,這裡只展示第一支,遞迴呼叫的步驟本質就是在按照這棵樹的層次順序來決定某個元素的選擇與否!

選擇第一個位置後的搜尋步驟如下圖:

這樣這個題目就很簡單了:

class Solution {
    
    public static List<List<Integer>> ret;
    public static boolean[] visited;
    public static int[] record;
    public static int num;
    
    public List<List<Integer>> permute(int[] nums) {
        
        ret=new LinkedList<List<Integer>>();
        num=nums.length;
        record=new int[num];
        visited=new boolean[num];
        recursive(nums,num);
        return ret;
    }
    
    public static void recursive(int[] nums,int k)
    {
        if(k==0)
        {
            LinkedList<Integer> tmp=new LinkedList<Integer>();
            for(int i=0;i<num;i++)
                tmp.add(record[i]);
            ret.add(tmp);
        }
        for(int i=0;i<nums.length;i++)
        {
            if(!visited[i])
            {
                record[k-1]=nums[i];
                visited[i]=true;
                recursive(nums,k-1);
                visited[i]=false;
            }
        }
    }
}