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


更多做法

LeetCode47.Permutations II(剑指offer38-1)的更多相关文章

  1. leetcode47. Permutations II

    leetcode47. Permutations II 题意: 给定可能包含重复的数字的集合,返回所有可能的唯一排列. 思路: 这题全排列两种写法. 用hash表记录已经visit的数字,虽然看起来很 ...

  2. 【LeetCode】137. 只出现一次的数字 II(剑指offer 56-II)

    137. 只出现一次的数字 II(剑指offer 56-II) 知识点:哈希表:位运算 题目描述 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 .请你找出并返回 ...

  3. 【算法训练营day8】LeetCode344. 反转字符串 LeetCode541. 反转字符串II 剑指Offer05. 替换空格 LeetCode151. 翻转字符串里的单词 剑指Offer58-II. 左旋转字符串

    [算法训练营day8]LeetCode344. 反转字符串 LeetCode541. 反转字符串II 剑指Offer05. 替换空格 LeetCode151. 翻转字符串里的单词 剑指Offer58- ...

  4. leetcode 203. Remove Linked List Elements 、83. Remove Duplicates from Sorted List 、82. Remove Duplicates from Sorted List II(剑指offer57 删除链表中重复的结点)

    203题是在链表中删除一个固定的值,83题是在链表中删除重复的数值,但要保留一个:82也是删除重复的数值,但重复的都删除,不保留. 比如[1.2.2.3],83题要求的结果是[1.2.3],82题要求 ...

  5. 剑指Offer38 数组所有数字出现两次,只有两个出现了一次,找出这两个数字

    /************************************************************************* > File Name: 38_Number ...

  6. 154. Find Minimum in Rotated Sorted Array II(剑指offer)

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...

  7. 剑指offer--38.左旋转字符串

    时间限制:1秒 空间限制:32768K 热度指数:173814 本题知识点: 字符串 题目描述 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果. ...

  8. 剑指offer38 数字在排序数组中出现的次数

    这种方法没用迭代,而是使用了循环的方式 class Solution { public: int GetNumberOfK(vector<int> data ,int k) { if(da ...

  9. 剑指Offer-38.平衡二叉树(C++/Java)

    题目: 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 分析: 可以从根节点开始遍历每一个节点,求得节点左右子树的最大高度,判断是不是平衡二叉树.这样做的问题在于会重复遍历节点,造成不必要的浪费. 所 ...

随机推荐

  1. Murano Weekly Meeting 2016.05.31

    Meeting time: 2016.May.31 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary: 1.A ...

  2. WSGI学习系列Pecan

    Pecan Introduce Pecan是一个轻量级的基于Python的Web框架, Pecan的目标并不是要成为一个“full stack”的框架, 因此Pecan本身不支持类似Session和D ...

  3. DEDE日期调用小插件

    在日期文本框里面,点击的时候,下面出来一个和万年历一样的日期选择表,在dede里面,有一个现成的js小插件,直接调用就OK了... <input type="text" on ...

  4. Spring Boot使用mongo的GridFS模块

    1. GridFS简介 GridFS是Mongo的一个子模块,使用GridFS可以基于MongoDB来持久存储文件.并且支持分布式应用(文件分布存储和读取).作为MongoDB中二进制数据存储在数据库 ...

  5. 判断表单中是否含有disabled属性

    我想判断input里面是否有disabled.或者选中未选中的selected  checked 属性时,需要用  prop()  方法,返回的结果是 true 或 false . attr()这个方 ...

  6. Window WindowManager 和WindowManager.LayoutParams

    <一> Window window是android中的窗口,表示顶级窗口的意思,也就是主窗口,它有两个实现类, PhoneWindow和MidWindow,我们一般的activity对应的 ...

  7. 轮播图jq版

    轮播图的需求 1:图片自己轮播,并且下面的tabs小图标跟着显示 2.鼠标hover到tabs上面显示对应的图片 3.点击左右按钮,显示下一张图片. <div id="oLunbo&q ...

  8. DevExtreme 搭建Node.js开发环境

    简介 DevExtreme is a component suite for creating highly responsive web applications for touch devices ...

  9. DIV+CSS图片不间断滚动jquery特效(Marquee插件)及移动标签marquee整理

    推荐一个jQuery的无缝文字滚动效果,同时也可以滚动图片,也叫做跑马灯效果. 此jquery插件,依托jquery库,能实现各种滚动效果,且让HTML代码符合W3C标准. marquee标签:创建一 ...

  10. Version Control&Git

    首先了解一下什么是版本控制: Version control (版本控制)是指对软件开发过程中各种程序代码.配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一. 其次版本控制最主要的功能 ...