原题链接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-----获取无重复项/有重复项序列的全排列相关推荐

  1. c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  2. [贪心|字符串] leetcode 3 无重复字符的最长子串

    [贪心|字符串] leetcode 3 无重复字符的最长子串 1.题目 题目链接 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例1: 输入: "abcabcbb" ...

  3. 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  4. 一天一道LeetCode(61-90)

    一天一道LeetCode(61-90) 文章目录 一天一道LeetCode(61-90) 61.旋转链表 62.不同路径 63.不同路径 II 64.最小路径和 65.有效数字(未解决) 66.加一 ...

  5. leetcode17. 电话号码的字母组合--每天刷一道leetcode算法系列!

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  6. leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  7. 每日一道leetcode(python)46. 全排列

    每日一道leetcode(python)46. 全排列 2021-08-25 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 .你可以 按任意顺序 返回答案.示例 1:输入:nums ...

  8. 每日一道 LeetCode (51):盛最多水的容器

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  9. 【最全!最完整解析!】 计算机中,执行一条指令所需要的时间称为指令周期,完成一项基本操作所需要的时间称为机器周期,时钟脉冲的重复周期称为重复周期。因此,()

    计算机中,执行一条指令所需要的时间称为指令周期,完成一项基本操作所需要的时间称为机器周期,时钟脉冲的重复周期称为重复周期.因此,() A. 时钟周期大于机器周期 B. 时钟周期等于机器周期 C. 机器 ...

最新文章

  1. python序列类型-什么是序列,Python序列详解(包括序列类型和常用操作)
  2. 卫星轨道推演计算相关知识点总结(含欧拉角、旋转矩阵、及各坐标系转化等)
  3. func_num_args()
  4. 伟大公司为什么需要技术型领导?
  5. matlab cam orbit,Matlab的绘图函数
  6. 火狐浏览器工具栏/折叠菜单怎么设置?火狐浏览器工具栏/折叠菜单定制教程
  7. 字符串的切割操作(strtok,split)
  8. html 文字过多如何显示,当页面文字过多时,怎么用css使超出部分显示省略号?(单/多行代码演示)...
  9. java 线程访问控件_多线程下访问控件的方式
  10. LNMP(linux+nginx+mysql+php)服务器环境配置
  11. 大数据可视化要避免的常见错误
  12. Kali内Nmap端口扫描与高级扫描
  13. 计算机网络是一个_______,计算机网络习题一、名词解释计算机网络,网络拓扑结构二、填空题1.计算机网络是__________与__________结...
  14. 难倒高手了,c语言枚举end的作用是什么?
  15. 虚拟运营商出牌:流量不清零难成杀手锏
  16. cocos2d-x的初步学习二十之坦克大战七
  17. 云计算中存储基础知识
  18. 一个显示器分屏显示两个画面_测了两个爆款游戏显示器,结果我发现他们都有坑。...
  19. 010 Editor:二进制文件编辑利器
  20. html 自动关机,电脑开机后自动关机

热门文章

  1. iconpath 微信小程序_【报Bug】微信小程序 map 标记点iconPath图标 苹果手机 不能单个设置了。以前没有问题。现在不知道为啥不行了...
  2. php无法下单功能,PHP如何解决并发下单问题?(不一定是下单,举个例)
  3. Winform控件拖动
  4. GCDWebUploader支持iOS进入后台后仍然可以进行传输
  5. exports、module.exports和export、export default到底是咋回事
  6. linux内核配置与编译
  7. C\C++ 位域操作
  8. 分享一个简单程序(webApi+castle+Automapper+Ef+angular)
  9. 字符串的压缩【百度】
  10. Java:多线程,CyclicBarrier同步器