题目:

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,2
3,2,1 → 1,2,3
1,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的更多相关文章

  1. LeetCode31 Next Permutation and LeetCode60 Permutation Sequence

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  2. [Swift]LeetCode31. 下一个排列 | Next Permutation

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  3. Permutation Sequence

    The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  4. [LeetCode] Palindrome Permutation II 回文全排列之二

    Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...

  5. [LeetCode] Palindrome Permutation 回文全排列

    Given a string, determine if a permutation of the string could form a palindrome. For example," ...

  6. [LeetCode] Permutation Sequence 序列排序

    The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  7. [LeetCode] Next Permutation 下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  8. 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 ...

  9. UVA11525 Permutation[康托展开 树状数组求第k小值]

    UVA - 11525 Permutation 题意:输出1~n的所有排列,字典序大小第∑k1Si∗(K−i)!个 学了好多知识 1.康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+ ...

随机推荐

  1. Visual Studio Profiler 跟踪检查每个exe dll 性能 执行时间 CPU占用情况的方法

  2. 启动 Eclipse 弹出“Failed to load the JNI shared library jvm.dll”错误

    原因1:给定目录下jvm.dll不存在. 对策:(1)重新安装jre或者jdk并配置好环境变量.(2)copy一个jvm.dll放在该目录下. 原因2:eclipse的版本与jre或者jdk版本不一致 ...

  3. ubuntu LVM

    本文介绍下,在ubuntu中扩展LVM磁盘的具体方法,有需要的朋友参考下吧. 当LV空间利用率较大即将耗尽LV空间时,可以将一块新的磁盘或一块磁盘上的/空间加入LV中. 现在/ 空间如下: 代码示例: ...

  4. 提升c++builder 代码输入流畅度的配置

    提高c++builder 代码输入流畅度 1.输入指针的函数名后,识别函数参数移动光标到括弧内,此功能太慢,有明显延迟,建议关闭.关闭以后,输入函数名不会自动添加(),需要自己手动输入括弧了,不过速度 ...

  5. 深刻理解Python中的元类metaclass(转)

    本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...

  6. LightOJ 1282 Leading and Trailing (快数幂 + 数学)

    http://lightoj.com/volume_showproblem.php?problem=1282 Leading and Trailing Time Limit:2000MS     Me ...

  7. C# JackLib系列之GdiHelper圆角矩形的快速生成

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  8. 手把手教你玩转SOCKET模型之重叠I/O篇(下)

    四.     实现重叠模型的步骤 作 了这么多的准备工作,费了这么多的笔墨,我们终于可以开始着手编码了.其实慢慢的你就会明白,要想透析重叠结构的内部原理也许是要费点功夫,但是只是学会 如何来使用它,却 ...

  9. uva 542 - France '98(概率)

    题目链接:uva 542 - France '98 题目大意:有16支球队比赛,给出16支球队的名称,然后给出16*16的表格,g[i][j] 表示i队胜j队的概率,问说16支球队获得总冠军的概率. ...

  10. Java获取IP地址:request.getRemoteAddr()注意

        在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户 ...