题目:

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. SQL Server 字符串函数

    字符串函数 在开发T-SQL时,经常会需要对字符串进行各种各样的操作,下面介绍常用的字符串函数. 1.获取字符的ASCII码 ASCII ASCII码是对字符的标准编码.要获取字符的ASCII码就可以 ...

  2. 关于VSS配置遇到的问题及解决方法

    今天安装网上的教程开始部署源代码管理器 相关工具 VSS安装包:http://url.cn/PolkN8 VSS汉化包:http://url.cn/PeHq1A 具体安装教程请参考:http://ww ...

  3. HDU 2035 人见人爱A^B 分类: ACM 2015-06-22 23:54 9人阅读 评论(0) 收藏

    人见人爱A^B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  4. 恢复HDFS误删数据

    [恢复HDFS误删数据] HDFS会为每一个用户创建一个回收站目录:/user/用户名/.Trash/,每一个被用户通过Shell删除的文件/目录,在系统回收站中都一个周期,也就是当系统回收站中的文件 ...

  5. Qt实现应用程序单实例运行--LocalServer方式

    使Qt应用程序能够单实例运行的典型实现方法是使用共享内存实现.该方法实现简单,代码简洁. 但有一个致命缺陷:共享内存(QSharedMemory)实现的单程序运行,当运行环境是UNIX时,并且程序不幸 ...

  6. UVa 1617 Laptop (贪心)

    题意:有n个长度为1的线段,确定它们的起点,使得第i个线段在[ri,di]之间,输出空隙数目的最小值. 析:很明显的贪心题,贪心策略是这样的,先把所有的区间排序,原则是按右端点进行排序,如果相等再按左 ...

  7. JAVA网站高并发解决方案

    一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单,随着互联网业务的不断丰富,网站 ...

  8. java复制File文件操作

    ==========================复制File操作========================= /**  *   * @param newPath要赋值的路径  * @para ...

  9. Java垃圾回收器

    一.Java垃圾回收器要负责完成以下3个任务: 1.分配内存 2.确保被引用对象的内存不被错误回收 3.回收不再被引用的对象的内存空间 二.垃圾回收是一个复杂而又耗时的操作.如果JVM花费过多的时间在 ...

  10. LEARUN 开发框架 /aspnetboilerplate ----上海力软信息技术有限公司

    LEARUN 开发框架 ----上海力软信息技术有限公司 http://www.learun.cn/ aspnetboilerplate    http://www.aspnetboilerplate ...