题目:

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. sqlserver安装相关问题

    最近在部署一个工程,数据库(sqlserver2005develop)遇到不少问题,下面将一一列出. 安装完毕后,无法连接到本地实例. 打开microsoft sql server 2005-> ...

  2. ajax 瀑布流实现

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. SQL Server 字符串函数

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

  4. quartz中关键类

    job job是一个接口,你对某一类job的定义,可以通过实现该接口来实现.例如为销售报告定义一个SalesReportJob,包含变量name. job可以使用的几个注解 @DisallowConc ...

  5. 关于PCB 3D 模型的快速导入方法

    altium designer中创建的3D library 只能查看3D效果,并没有其他功能,经测试在原理图编辑界面通过给元件添加 PCB 3D 并不能真正添加3D模型,这样添加根本没有效果(显示不出 ...

  6. C++视频课程小结(2)

    C++远征之离港篇 章节介绍: 每章小结: 第一章:大致讲了一下本章会讲的内容:引用vs指针.const vs #define(这个我在C里都没用过).函数变得更强大.内存管理要小心之类的. 第二章: ...

  7. HDU 2859 Phalanx (dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2859 给你一个n*n的矩阵,问你最大的对称度是多少(左下右上为对称线) dp[i][j]表示i行j列元 ...

  8. SQL SERVER 2005如何建立自动备份的维护计划

    SQL Server 2005中可以使用维护计划来为数据库自动备份,减少数据库管理员的工作负担.其使用方法如下: (1)启动[sql server Management Studio],在[对象资源管 ...

  9. Oracle复制表结构和表数据

    一, 复制表结构及数据 create table z_xudebiao_test as select * from v_topic v where v.adddate > to_date('20 ...

  10. Generate the Jobs script from msdb Database

    前两周,由于数据库简繁体的转换,大量的数据库需要转到新的服务器. 在转其中的一台的时候,原先导出来的JOBS脚本不翼而飞(原因至今未明),而恰巧这一台服务器有90多个JOB(看下图恢复后的,注意滚动条 ...