1. 程式人生 > >DFS-帶重複元素的全排列

DFS-帶重複元素的全排列

此題是全排列問題的變形,給出的列表中有重複數字,需要去重。解決全排列問題的思路參見DFS-全排列問題

去重思路:以[1,2,2]為例,可以要求index=1的數字2在最後生成的排列中一定要在index=2的數字2的前面,強制規定了順序,避免了重複。即先從小到大排序,使相同的數字聚在一起,若前後2個數字相同,訪問後一個數字的時候,前一個數字必須已經訪問過了。只需新增一行程式碼

if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue;
完整的程式碼如下:
class Solution {
public:
    /*
     * @param :  A list of integers
     * @return: A list of unique permutations
     */
    vector<vector<int>> permuteUnique(vector<int> &nums) {
        // write your code here
        //先進行排序
        sort(nums.begin(),nums.end());
        vector<vector<int>> res;
        vector<int> tmp;
        vector<bool> visited(nums.size(),false);//訪問陣列,初始化全為false
        DFS(res,tmp,visited,nums,0);
        return res;
    }
    void DFS(vector<vector<int>>& res,vector<int>& tmp,vector<bool>& visited,vector<int> &nums,int index){
        if(index==nums.size()){//收斂條件
            res.push_back(tmp);
            return;
        }
        for(int i=0;i<nums.size();++i){
            if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue;
            if(!visited[i]){//沒有訪問過
                visited[i]=true;
                tmp.push_back(nums[i]);
                DFS(res,tmp,visited,nums,index+1);
                visited[i]=false;
                tmp.pop_back();
            }
        }
    }
};

理解不清楚的話還是畫圖理解的較快,用不同的顏色標記2個相同的數字2,紅色的2要在藍色的2前面(劃紅色斜線表示由於visited陣列作用,避免對同一位置的元素重複使用,為了簡單,只畫了部分)


if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue;即去除了訪問後面元素時,前一個元素還沒有被訪問的情況,完成了去重的任務