作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/next-permutation/description/

题目描述

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 and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

题目大意

找到一个排列按照字母表顺序的情况下,下一个更大的排列是多少。如果已经是最大的,那么应该翻转。必须原地翻转。

解题方法

逆序数字交换再翻转

很有技巧的题目。

先找到从后向前数,第一个降序的位置,把此位置后面的翻转。再把这个降序数字和后面第一个比它大的位置交换即可。

首先说一下这题怎么想到的。有如下的一个数组

1  2  7  4  3  1

下一个排列为:

1  3  1  2  4  7

观察可以发现,再给出的数组中,2之后的数字都是降序排列的,我们把2后面第一个比2大的数字放到最前面,然后让3后面的数字升序排列。

简单思路的证明:从7开始是降序的,也就是说7 4 3 1不可能通过重新排列构成更大的数字。如果要得到next permutation,那么必须把2这个位置的数字给换掉才行,而且只能换成比2大的数字在才能使next permutation > current permutation.至于换成多大的数字,很明显的需要换成在2后面的数字中刚好比2大的数字,证明可以使用反证法来说明换成其他数字要么比当前数字小,要么大于正确的next permutation.

下面这个做法是先逆序再交换,本质和上面的证明一样:

如果从第n个数字到最后都是递减的并且第n-1个数字小于第n个,说明从第n个数字开始的这段序列是字典序组合的最后一个,在下一个组合中他们要倒序变为字典序第一个,然后从这段序列中找出第一个大于第n-1个数字的数和第n-1个数字交换就可以了。

举个栗子,当前组合为12431,可以看出431是递减的,同时4>2,这样我们把431倒序,组合就变为12134,然后从134中找出第一个大于2的数字和2交换,这样就得到了下一个组合13124。对于完全递减的组合例如4321在倒序之后就可以结束了。

代码如下:

class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
n = len(nums)
i = n - 1
while i > 0 and nums[i] <= nums[i - 1]:
i -= 1
self.reverse(nums, i, n - 1)
if i > 0:
for j in range(i, n):
if nums[j] > nums[i-1]:
self.swap(nums, i-1, j)
break def reverse(self, nums, i, j):
"""
contains i and j.
"""
for k in range(i, (i + j) / 2 + 1):
self.swap(nums, k, i + j - k) def swap(self, nums, i, j):
"""
contains i and j.
"""
nums[i], nums[j] = nums[j], nums[i]

也可以先进行交换,然后再翻转。比如Leetcode的这个解答方式:

C++代码如下:

class Solution {
public:
void nextPermutation(vector<int>& nums) {
const int N = nums.size();
int i = N - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) --i;
int j = N - 1;
if (i >= 0) {
while (nums[j] <= nums[i]) --j;
swap(nums[i], nums[j]);
}
reverse(nums.begin() + i + 1, nums.end());
}
};

库函数

这个算我第一次觉得C++让人惊呆吧,有next_permutation函数,而且是原地操作。

class Solution {
public:
void nextPermutation(vector<int>& nums) {
next_permutation(nums.begin(), nums.end());
}
};

参考资料:

  1. https://leetcode.com/articles/next-permutation/
  2. https://blog.csdn.net/tstsugeg/article/details/50261517
  3. http://www.cnblogs.com/grandyang/p/4428207.html

日期

2018 年 8 月 27 日 ———— 就要开学了!
2019 年 1 月 14 日 —— 凛冬将至

【LeetCode】31. Next Permutation 解题报告(Python & C++)的更多相关文章

  1. 【LeetCode】784. Letter Case Permutation 解题报告 (Python&C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 循环 日期 题目地址:https://leet ...

  2. 【LeetCode】Permutations II 解题报告

    [题目] Given a collection of numbers that might contain duplicates, return all possible unique permuta ...

  3. 【LeetCode】120. Triangle 解题报告(Python)

    [LeetCode]120. Triangle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址htt ...

  4. 【LeetCode】Gas Station 解题报告

    [LeetCode]Gas Station 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/gas-station/#/descr ...

  5. LeetCode 1 Two Sum 解题报告

    LeetCode 1 Two Sum 解题报告 偶然间听见leetcode这个平台,这里面题量也不是很多200多题,打算平时有空在研究生期间就刷完,跟跟多的练习算法的人进行交流思想,一定的ACM算法积 ...

  6. [array] leetcode - 31. Next Permutation - Medium

    leetcode - 31. Next Permutation - Medium descrition Implement next permutation, which rearranges num ...

  7. LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation]

    LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation] <c++> LeetCode 31 Next Pe ...

  8. 【LeetCode】Island Perimeter 解题报告

    [LeetCode]Island Perimeter 解题报告 [LeetCode] https://leetcode.com/problems/island-perimeter/ Total Acc ...

  9. 【LeetCode】01 Matrix 解题报告

    [LeetCode]01 Matrix 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/01-matrix/#/descripti ...

随机推荐

  1. fping (比ping更强大的ping工具)

    Fping程序类似于ping(ping是通过ICMP(网络控制信息协议InternetControl Message Protocol)协议回复请求以检测主机是否存在).Fping与ping不同的地方 ...

  2. 微信小程序调试bug-日程计划类

    首先嘤嘤嘤一下,破bug,改了我一天,摔(′д` )-彡-彡 写的个微信小程序 逻辑如下,正常的功能是,我可以新建,修改,查询(按筛选条件),删除某个日程信息,后面贴个页面,我的bug出现就很搞笑了, ...

  3. 构建LNMP+WordPress

    1. 安装LNMP环境 首先修改主机名 [root@samba ~]# hostnamectl set-hostname lnmp[root@lnmp lnmp1.6-full]# hostnamec ...

  4. 学习java的第二十六天

    一.今日收获 1.java完全学习手册第三章算法的3.2排序,比较了跟c语言排序上的不同 2.观看哔哩哔哩上的教学视频 二.今日问题 1.快速排序法的运行调试多次 2.哔哩哔哩教学视频的一些术语不太理 ...

  5. JDBC01 获取数据库连接

    概述 Java Database Connectivity(JDBC)直接访问数据库,通用的SQL数据库存取和操作的公共接口,定义访问数据库的标准java类库(java.sql,javax.sql) ...

  6. Azure Key Vault(二)- 入门简介

    一,引言 在介绍 Azure Key Vault 之前,先简单介绍一下 HSM(硬件安全模块). -------------------- 我是分割线 -------------------- 1,什 ...

  7. Mybatis中 SIMPLE、REUSE、BATCH的区别

    Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...

  8. jQuery中的html()、text()和val()的用法

    1.html() 获得的是第一个符合要求的标签中的所有内容,例如: var content = $("li").html(); <li>111<p>999& ...

  9. 【阿菜漏洞复现】DeFi 平台 MonoX Finance 漏洞分析及复现

    前言 2021 年 11 ⽉ 30 ⽇,DeFi 平台 MonoX Finance 遭遇攻击,损失共计约 3100 万美元. 造成本次攻击的漏洞主要有两个: 移除流动性的函数未对调用者进行检测,使得任 ...

  10. Linux下安装Calibre

    目录 一.介绍 二.安装 三.测试 四.报错处理 一.介绍 Calibre是基于python的电子书制作软件,可导出PDF.EPUB.MOBI.Word格式电子书. 二.安装 yum -y insta ...