LeetCode31 Next Permutation
题目:
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. (Medium)1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1
分析:
题意就是找下一个排列,首先可以先复习使用一下STL的next_permutation。
调用next_permutation肯定是能过的。
代码:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
next_permutation(nums.begin(), nums.begin() + nums.size());
}
};
用next_permutation生成全排列举例如下(参考C++ reference)
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation, std::sort int main () {
int myints[] = {,,}; std::sort (myints,myints+); std::cout << "The 3! possible permutations with 3 elements:\n";
do {
std::cout << myints[] << ' ' << myints[] << ' ' << myints[] << '\n';
} while ( std::next_permutation(myints,myints+) ); std::cout << "After loop: " << myints[] << ' ' << myints[] << ' ' << myints[] << '\n'; return ;
}
所以一般用到next_permutation的题目就是在上面循环的do里面对每次生成的排列做文章。
回头再来看看实现:
这个算法的实现貌似是一个诞生了几百年的经典算法,但是很不好理解其做法的原因,自己梳理一下。
首先要注意的是,我们动一个元素的时候,应该想要改变之后的增值尽可能小。如 124653 -> 125346;
也就是说,高位应该尽量一致,能动低位的时候就不要动高位。如上例子,当4改成5就能增大的时候,不要动1,2。
那4是如何找到的,也就是说最后一个能动的地位是谁呢? 这就应该从后往前看,显然53没得动,653也没得动,但4653可以动了。
原因在于,如果从后往前看的时候,得到的后方元素都是递减的,也就是在这一局部(比如653)他已经没有next_permutation了,所以要再向前找。
只到发现一个位置i, nums[i] < nums[i+1]这意味着 nums[i....size-1] (如4653)这一局部是还有next_permutation。所以位置 i 就是需要被交换。
但他应该交换谁呢?还是考虑上面说的想要改变之后的增值尽可能小,所以应该交互大于nums[i]的最小值,也就是后面位置中从后往前数(从小往大数)第一个大于nums[i]的元素。
当交换完之后,即例子中变为125643,可以发现。nums[i+1,...size-1](即643)一定是完全降序的。
所以为了能组成元素的最小值(这样增值才最小),应该reverse这一部分,变为(346)
得到最终结果125346。
所以综合来讲,算法的流程是(伪代码):
It i = end - ;
while ( (*i > *(i+) )) //找第一个小于后续元素的位置
/* pass */; It j = end;
while ( *j < *i ) //找第一个大于*i的元素
/*pass */ iter_swap(i, j); //交换 *i , *j
reverse(i+, end); // reverse *(i+1)到*end
return true;
代码:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
if (nums.size() < ) {
return;
}
int i = nums.size() - ;
for (i; i >= ; i--) {
if (nums[i] < nums[i+]) {
break;
}
}
if (i == -) {
sort(nums.begin(), nums.end());
return;
}
int j = nums.size() - ;
for (j; j > i; j--) {
if (nums[j] > nums[i]) {
break;
}
}
swap(nums[i], nums[j]);
reverse(nums.begin() + i + , nums.end());
}
};
LeetCode31 Next Permutation的更多相关文章
- LeetCode31 Next Permutation and LeetCode60 Permutation Sequence
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- [Swift]LeetCode31. 下一个排列 | Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Palindrome Permutation II 回文全排列之二
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [LeetCode] Palindrome Permutation 回文全排列
Given a string, determine if a permutation of the string could form a palindrome. For example," ...
- [LeetCode] Permutation Sequence 序列排序
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Next Permutation 下一个排列
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- Leetcode 60. Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- UVA11525 Permutation[康托展开 树状数组求第k小值]
UVA - 11525 Permutation 题意:输出1~n的所有排列,字典序大小第∑k1Si∗(K−i)!个 学了好多知识 1.康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+ ...
随机推荐
- Spark RDD概念学习系列之为什么会引入RDD?(一)
为什么会引入RDD? 我们知道,无论是工业界还是学术界,都已经广泛使用高级集群编程模型来处理日益增长的数据,如MapReduce和Dryad.这些系统将分布式编程简化为自动提供位置感知性调度. ...
- cocos2dx android版本移植时的Error format not a string literal and no format arguments解决方案
原文地址 : http://www.cnblogs.com/hhuang2012/p/3336911.html cocos2dx android版本移植时的Error format not a str ...
- RedHat/CentOS6.4---永久关闭iptables
今天无意中发现一个现象,当我关闭iptables并且停止iptables服务,但是总会有一些出奇的事情发生,当我再次启动系统,查看iptables状态,iptables又自动开启,很是无奈啊!在Red ...
- hdu 2444 The Accomodation of Students(最大匹配 + 二分图判断)
http://acm.hdu.edu.cn/showproblem.php?pid=2444 The Accomodation of Students Time Limit:1000MS Me ...
- 使用UIGestureRecognizer监听屏幕事件
转载自 http://blog.csdn.net/samguoyi/article/details/7911499 如果只是想获取屏幕点击事件有一个最简单的办法,就是写一个透明的uibutton覆盖 ...
- Codeforces 600 E. Lomsat gelral (dfs启发式合并map)
题目链接:http://codeforces.com/contest/600/problem/E 给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少. 最容 ...
- sql GROUP BY 分组统计
语句1: SELECT TypeID, COUNT(*) AS [count] FROM GoodsInfo GROUP BY TypeID 得到结果 解析结果:GoodsInfo表有 4条记录, ...
- C#和JavaScript的区别
Strong and Loose Typing: 强弱比较 // C# var customer = new Customer(); //var is compiler inferred //Java ...
- setTimeout setInterval 区别 javascript线程解释
原文:http://www.iamued.com/qianduan/1645.html 今天看到这篇文章,学到了不少东西 特此发出来 和大家分享 JavaScript的setTimeout与setIn ...
- Innodb的事务与日志 & JTA事务
InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的 通过 行多版本控制 MyISAM Innodb 事物支持 : 不支持 ...