leetcode

来源:互联网 发布:数据流量 英文 编辑:程序博客网 时间:2024/06/15 15:04

47. Permutations II

Given a collection of numbers that mightcontain duplicates, return all possible unique permutations.

 

For example,

[1,1,2] have the following uniquepermutations:

[

 [1,1,2],

 [1,2,1],

 [2,1,1]

]

 

一题全排列的题目,并且在同一个集合里会出现重复的数字,这就需要除去相同序列,这里有两种方式:

一种是使用set来存储序列;

另外一种就是在遍历时就除去相同的序列;

两种方法本质上都是dfs。在solution板块看到了别人的解答,感觉受到启发。

这是一种在遍历时就除去相同的序列的方法。

 

算法思想

方法1:(使用set来除去相同的序列)

使用一个临时的线性表来保存当前的序列,并且再利用一个vis的线性表来保存访问记录,深度优先遍历(dfs)将未访问过的元素加入到临时的线性表中,加入元素至n个之后,将临时线性表加入set。

 

这里的主要时间花费在,dfs所花时间,O(n!),以及加入set中进行比较的时间O(nlogn),这显得有点不可以接受,不过总是比存在一个二维表里进行比较的O(n^2)要好上一点,最好的是利用hash_table,但操作难度就比较大。这里比较好的是只需要额外的操作空间是O(n)。

 

 

方法2:(在遍历过程中除去算法)

 

先将给定线性表排好序(方便遇上相同元素时直接跳过),然后进行遍历,当遇上相同元素时,直接跳入下一次遍历。

 

这里最重要的花费仍旧是dfs,还有就是拷贝vector所需要的代价,每一层迭代都要拷贝一个临时的vector。算法实现起来比较抽象,没有方法1那么简单。两种方法各有千秋,但在提交的时候偏向于第二种算法,运行时间相对较短。




class Solution {public:    vector < vector<int> > ret;    vector <int> tmp;    set < vector<int> > my_set;    vector<vector<int>> permuteUnique(vector<int>& nums) {        //sort(nums.begin(), nums.end());        vector<int> vis(nums.size(),0);        //helper(nums,0,nums.size());        helper2(nums,vis,nums.size());        for(auto it = my_set.begin() ; it != my_set.end() ; ++it)ret.push_back(*it);        return ret;    }    void helper(vector<int> v , int i, int j){        if(i == j-1) {ret.push_back(v);return;}        for(int k = i ; k < j  ; ++k){            if(k != i && v[k] == v[i])continue;            swap(v[i],v[k]);            helper(v,i+1,j);        }                    }        void helper2(vector<int>& v , vector<int>& vis , int n){        if(n == 0){my_set.insert(tmp);return;}        for(int i = 0 ; i < v.size() ; ++i){            if(!vis[i]){                vis[i] = 1;                tmp.push_back(v[i]);                helper2(v,vis,n-1);                vis[i] = 0;                tmp.pop_back();            }                    }            }};


原创粉丝点击