每天一道LeetCode-----获取无重复项/有重复项序列的全排列
原题链接Permutations
要求是输出给定序列的全排列,序列中不包含重复元素
STL
中有next_permutation
函数可以获取当前序列的下一个排列,使用起来也很简单,先对序列按递增顺序排序,然后不断调用next_permutation
函数获取当前序列的下一个更大的排列,如果没有更大的排列就返回false
class Solution {
public:vector<vector<int>> permute(vector<int>& nums) {std::sort(nums.begin(), nums.end());vector<vector<int>> res;res.emplace_back(nums);}while(next_permutation(nums.begin(), nums.end()));return res;}
};
这里主要是利用另一种方法实现,做个记录
对于全排列问题,又是没有重复项的序列,可以采用不断交换两个位置的方法获得所有的排列,即以某个点为开始点,依次和后面的做交换,因为没有重复项,所以得到的序列都是不同的结果,例如
1 2 3
/* * 开始点为第一个数* 1和2交换 ->2 1 3 * 1和3交换 ->3 2 1*/2 1 3
/** 从2 1 3递归* 开始点为第二个数* 1和3交换 ->2 3 1*/3 2 1
/** 从3 2 1递归* 开始点为第二个数* 2和1交换 ->3 1 2*//* 结果 */
1 2 3
2 1 3
2 3 1
3 1 2
3 2 1
但是这种方法少了一种结果,{1 3 2}
。因为序列{1 2 3}的时候是以1为开始点,但是没有对2和3进行交换。原因在于没有从{1 2 3}
递归并且开始点是第二个数的过程。所以,解决办法就是当开始点进行交换时,也要和自己交换一次,但是交换的结果不能添加到结果中。但是这样对于第一个序列{1 2 3}
就不在结果中,所以需要在交换前手动添加第一个序列。
代码如下
class Solution {
public:vector<vector<int>> permute(vector<int>& nums) {/* 从大到小排序 */std::sort(nums.begin(), nums.end());vector<vector<int>> res;/* 添加最初的序列 */res.push_back(nums);get_permutation(nums, 0, res);return res;}
private:void get_permutation(vector<int>& nums, int idx, vector<vector<int>>& res){if(idx >= nums.size())return;/* 以idx位置作为开始点,依次和后面的交换 */for(int i = idx; i < nums.size(); ++i){/* 交换,获取一个排列 */swap(nums[i], nums[idx]);/* 如果不是自己和自己交换,就把排列添加到结果中 */if(i != idx)res.push_back(nums);/* 递归调用,以下一个位置作为开始点 */get_permutation(nums, idx + 1, res);/* 交换完再换回来,回到开始的状态,然后和下一个交换 */swap(nums[i], nums[idx]);}}
};
扩展
Permutations II
原题链接Permutations II
和上面要求一样,唯一区别是给定的序列可能有重复的元素
如果再按照上面的方法,那么会出现大量重复的结果,比如第一个1和第二个1交换,结果没有变换,但是被添加了两次。所以,在进行交换的时候,需要特别注意,以当前位置作为开始点和后面的元素进行交换时,这个元素在之前有没有交换过,如果交换过了,就不用再交换了。
例如,如果开始时序列为{1 2 7 7 9}
,某次交换以2为开始点
/* swap(nums[1], nums[2]) -> 1 7 2 7 9 */
开始点为第2个数2,2先和第一个7交换,变为1 7 2 7 9/* swap(nums[2], nums[3]) -> 1 7 7 2 9 */
开始点变为第3个数7,7先和2交换,变为1 7 2 7 9/* ... */交换一轮后回到1 2 7 7 9
/* swap(nums[1], nums[3]) -> 1 7 7 2 9 */
开始点为第2个数2,2和第二个7交换,变为1 7 7 2 9
此时已经和先前的结果重复了
原因就在于如果有重复的元素,那么开始点第一次和重复元素的第一个元素交换,接着和第二个元素交换获取的排列,和开始点直接和重复元素的第二个元素交换获取的排列是一样的
所以,只需要和重复元素的第一个元素交换一次即可,后面重复的元素都不需要再次交换,因为在向后递归的过程中,开始点和后面的重复元素已经交换过了。
代码如下
class Solution {
public:vector<vector<int>> permuteUnique(vector<int>& nums) {/* 递增排序 */std::sort(nums.begin(), nums.end());vector<vector<int>> res;/* 添加原始排列 */res.push_back(nums);get_permutation(nums, 0, res);return res;}
private:void get_permutation(vector<int>& nums, int idx, vector<vector<int>>& res){if(idx >= nums.size())return;/* 记录是否有交换过 */std::unordered_set<int> hash;for(int i = idx; i < nums.size(); ++i){if(hash.find(nums[i]) != hash.end())continue;hash.insert(nums[i]);swap(nums[i], nums[idx]);if(i != idx)res.push_back(nums);get_permutation(nums, idx + 1, res);swap(nums[i], nums[idx]);}}
};
每天一道LeetCode-----获取无重复项/有重复项序列的全排列相关推荐
- c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- [贪心|字符串] leetcode 3 无重复字符的最长子串
[贪心|字符串] leetcode 3 无重复字符的最长子串 1.题目 题目链接 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例1: 输入: "abcabcbb" ...
- 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- 一天一道LeetCode(61-90)
一天一道LeetCode(61-90) 文章目录 一天一道LeetCode(61-90) 61.旋转链表 62.不同路径 63.不同路径 II 64.最小路径和 65.有效数字(未解决) 66.加一 ...
- leetcode17. 电话号码的字母组合--每天刷一道leetcode算法系列!
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 每日一道leetcode(python)46. 全排列
每日一道leetcode(python)46. 全排列 2021-08-25 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 .你可以 按任意顺序 返回答案.示例 1:输入:nums ...
- 每日一道 LeetCode (51):盛最多水的容器
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
- 【最全!最完整解析!】 计算机中,执行一条指令所需要的时间称为指令周期,完成一项基本操作所需要的时间称为机器周期,时钟脉冲的重复周期称为重复周期。因此,()
计算机中,执行一条指令所需要的时间称为指令周期,完成一项基本操作所需要的时间称为机器周期,时钟脉冲的重复周期称为重复周期.因此,() A. 时钟周期大于机器周期 B. 时钟周期等于机器周期 C. 机器 ...
最新文章
- python序列类型-什么是序列,Python序列详解(包括序列类型和常用操作)
- 卫星轨道推演计算相关知识点总结(含欧拉角、旋转矩阵、及各坐标系转化等)
- func_num_args()
- 伟大公司为什么需要技术型领导?
- matlab cam orbit,Matlab的绘图函数
- 火狐浏览器工具栏/折叠菜单怎么设置?火狐浏览器工具栏/折叠菜单定制教程
- 字符串的切割操作(strtok,split)
- html 文字过多如何显示,当页面文字过多时,怎么用css使超出部分显示省略号?(单/多行代码演示)...
- java 线程访问控件_多线程下访问控件的方式
- LNMP(linux+nginx+mysql+php)服务器环境配置
- 大数据可视化要避免的常见错误
- Kali内Nmap端口扫描与高级扫描
- 计算机网络是一个_______,计算机网络习题一、名词解释计算机网络,网络拓扑结构二、填空题1.计算机网络是__________与__________结...
- 难倒高手了,c语言枚举end的作用是什么?
- 虚拟运营商出牌:流量不清零难成杀手锏
- cocos2d-x的初步学习二十之坦克大战七
- 云计算中存储基础知识
- 一个显示器分屏显示两个画面_测了两个爆款游戏显示器,结果我发现他们都有坑。...
- 010 Editor:二进制文件编辑利器
- html 自动关机,电脑开机后自动关机
热门文章
- iconpath 微信小程序_【报Bug】微信小程序 map 标记点iconPath图标 苹果手机 不能单个设置了。以前没有问题。现在不知道为啥不行了...
- php无法下单功能,PHP如何解决并发下单问题?(不一定是下单,举个例)
- Winform控件拖动
- GCDWebUploader支持iOS进入后台后仍然可以进行传输
- exports、module.exports和export、export default到底是咋回事
- linux内核配置与编译
- C\C++ 位域操作
- 分享一个简单程序(webApi+castle+Automapper+Ef+angular)
- 字符串的压缩【百度】
- Java:多线程,CyclicBarrier同步器