题目:

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()); }
};
 

最新文章

  1. APUE学习之多线程编程(二):线程同步
  2. js工作中日常问题集中
  3. Python常用函数、方法、模块记录
  4. 基于Oracle的Mybatis 批量插入
  5. Ranorex 5 发布,支持SAP、Oracle Forms、MS Dynamics等
  6. android 学习随笔六(网络要求及配置)
  7. EntityFramework5.0CodeFirst全面学习
  8. iOS-音频格式转换-b
  9. Windbg调试命令详解(3)
  10. CSAPP LAB: Buffer Overflow
  11. Win7 公布网站 HTTP 错误 404.4 - Not Found
  12. http://www.sufeinet.com/thread-655-1-1.html
  13. 关于python命令在editor里编写与在interpreter里的编写的不同之处
  14. windows server 2003断开远程之后自动注销用户
  15. C#3.0导航
  16. standby_file_management参数为MANUAL导致添加数据文件错误
  17. 关于OSI
  18. HTML(一)
  19. Implicit conversion from enumeration type &#39;enum CGImageAlphaInfo&#39; to different enumeration type &#39;CGBitmapinfo&#39; (aka) &#39;enum CGBitmapInfo&#39;)
  20. English trip -- Review Unit7 Shopping 购物

热门文章

  1. 在linnux下,配置自动备份oacle
  2. TDBXCommand TDBXReader
  3. 在VS2013中使用水晶报表
  4. poj 2594 Treasure Exploration(最小路径覆盖+闭包传递)
  5. 在类库中使用Session
  6. TCP/IP TIME_WAIT状态原理
  7. 查看系统和PowerShell版本
  8. 分享一个客户端程序(winform)自动升级程序,思路+说明+源码
  9. 【M35】让自己习惯于标准C++语言
  10. 【M32】在未来时态下发展程序