LeetCode47.Permutations II(剑指offer38-1)

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

Example:

Input: [1,1,2]
Output:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

法1.递归。swap.回溯。唯一要多做的就是去重。用unordered_set的insert就行。因为用的是hash的无序集合,所以要用std::sort重排一下。

细节:string 的长度 .size()或者.length()都是一样的。

而strlen(const char *)  形参类型是常量字符指针。

class Solution {
public:
    vector<string> Permutation(string str)
    {
        vector<string> ret;
        if(str.size()==0) return ret; 
        Helper(str, 0,ret);
        
        unordered_set<string> myset;//去重
        ret = Helper2(ret,myset);
        return ret;
    }
    
    //fixed:[0:start-1]
    //result:[start:size()-1]
    void Helper(string str,int start,vector<string> &ret)
    {
        if(start==str.size())//string::size()和string::length()一样的。
        {
            ret.push_back(str);
            return;
        }
        //[start:size()-1]全排列
        for(int i =start ;i<str.size();i++)//
        {
            swap(str[i],str[start]);
            Helper(str, start+1,ret);
            swap(str[i],str[start]);
        }
    }
    
    vector<string> Helper2(vector<string> ret,unordered_set<string> &myset)
    {
        for(auto str:ret)
        {
            myset.insert(str);
        }
        vector<string> rets;
        for(auto str:myset)
        {
            rets.push_back(str);
        }
        sort(rets.begin(),rets.end());
        return rets;
    }
};

 


 法2.递归。更简单的递归。用红黑树实现的set,是本身就已经排序好的有序集合。

细节。 return vector<vector<int>>(ret.begin(),ret.end());这种写法是对的。在leetcode里面只能用有序集合。否则用unordered_set报错:需要实现特定的hash函数。

error: static assertion failed: hash function must be invocable with an argument of key type
class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        unordered_set<vector<int>> ret;
        if(nums.empty())
            return vector<vector<int>>();
        Helper(nums,0,ret); 
        return vector<vector<int>>(ret.begin(),ret.end());

    }

    void Helper(vector<int> nums,int start,unordered_set<vector<int>> &ret)
    {
        if(start==nums.size())
        {
            ret.insert(nums);
            return;
        }
        for(int i=start;i<nums.size();i++)
        {
            swap(nums[i],nums[start]);
            Helper(nums,start+1,ret);
            swap(nums[i],nums[start]);
        }
    } 
};

 


unordered_set容器中的key是无序的,就不满足上述递增要求了,而set能保证容器中key有序。

set能保持有序,因为底层基于RB-Tree,天然的有序结构,而unordered_set底层则是hashtable。

记得当时用unordered_set做class或者struct的容器时就得实现特定的hash函数,当元素较少、hash bucket很多的时候,负载因子很小,发生冲突的概率很小,这样保证了unordered_set的查找效率。因此,在负载因子大于某个常数(1或者0.75)就需要对哈希表进行扩容。

下面一个测试看出在使用上set和unordered_set区别 

int main()
{
	set<int>s1;
	unordered_set<int>s2;
	s1.insert(4);
	s1.insert(2);
	s1.insert(3);
	s1.insert(1);
	s2.insert(4);
	s2.insert(2);
	s2.insert(3);
	s2.insert(1);
	for (auto it = s1.begin(); it != s1.end(); ++it)
		cout << *it << " ";
	cout << endl;
	for (auto it = s2.begin(); it != s2.end(); ++it)
		cout << *it << " ";
	cout << endl;
} 

输出:

1 2 3 4

4 2 3 1


更多做法

posted @ 2019-03-02 18:00 lightmare 阅读(...) 评论(...) 编辑 收藏