【LeetCode】31. Next Permutation 解题报告(Python & C++)
作者: 负雪明烛
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());
}
};
参考资料:
- https://leetcode.com/articles/next-permutation/
- https://blog.csdn.net/tstsugeg/article/details/50261517
- http://www.cnblogs.com/grandyang/p/4428207.html
日期
2018 年 8 月 27 日 ———— 就要开学了!
2019 年 1 月 14 日 —— 凛冬将至
【LeetCode】31. Next Permutation 解题报告(Python & C++)的更多相关文章
- 【LeetCode】784. Letter Case Permutation 解题报告 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 循环 日期 题目地址:https://leet ...
- 【LeetCode】Permutations II 解题报告
[题目] Given a collection of numbers that might contain duplicates, return all possible unique permuta ...
- 【LeetCode】120. Triangle 解题报告(Python)
[LeetCode]120. Triangle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址htt ...
- 【LeetCode】Gas Station 解题报告
[LeetCode]Gas Station 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/gas-station/#/descr ...
- LeetCode 1 Two Sum 解题报告
LeetCode 1 Two Sum 解题报告 偶然间听见leetcode这个平台,这里面题量也不是很多200多题,打算平时有空在研究生期间就刷完,跟跟多的练习算法的人进行交流思想,一定的ACM算法积 ...
- [array] leetcode - 31. Next Permutation - Medium
leetcode - 31. Next Permutation - Medium descrition Implement next permutation, which rearranges num ...
- LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation]
LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation] <c++> LeetCode 31 Next Pe ...
- 【LeetCode】Island Perimeter 解题报告
[LeetCode]Island Perimeter 解题报告 [LeetCode] https://leetcode.com/problems/island-perimeter/ Total Acc ...
- 【LeetCode】01 Matrix 解题报告
[LeetCode]01 Matrix 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/01-matrix/#/descripti ...
随机推荐
- chmod文件权限分配问题
一. 文件(文件夹)的权限问题 一个文件或者文件夹,使用它的人有三类:root.当前用户和其他用户,例如,我们可以通过 ls -l xxx.xxx 来查看文件 "xxx.xxx" ...
- 8.7 进程间的通讯:管道、消息队列、共享内存、信号量、信号、Socket
进程间的通讯 进程间为什么需要通讯? 共享数据.数据传输.消息通知.进程控制 进程间的通讯有哪些类型? 首先,联系前面讲过的知识,进程之间的用户地址空间是相互独立的,不能进行互相访问,但是,内核空间却 ...
- flink02------1.自定义source 2. StreamingSink 3 Time 4窗口 5 watermark
1.自定义sink 在flink中,sink负责最终数据的输出.使用DataStream实例中的addSink方法,传入自定义的sink类 定义一个printSink(),使得其打印显示的是真正的ta ...
- Angular 中 [ngClass]、[ngStyle] 的使用
1.ngStyle 基本用法 1 <div [ngStyle]="{'background-color':'green'}"></<div> 判断添加 ...
- 简化版chmod
我们知道对文件访问权限的修改在Shell下可通过chmod来进行 例如 可以看到v.c文件从无权限到所有者可读可写可执行.群组和其他用户可读可执行 chmod函数原型 int chmod(const ...
- 【Netty】最透彻的Netty原理架构解析
这可能是目前最透彻的Netty原理架构解析 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给大家在实际开发实践.学习开源项目方面提供参考. ...
- 监测linux系统负载与CPU、内存、硬盘、用户数的shell脚本
本节主要内容: 利用Shell脚本来监控Linux系统的负载.CPU.内存.硬盘.用户登录数. 一.linux系统告警邮件脚本 # vim /scripts/sys-warning.sh #!/bin ...
- Oracle存储过程游标for循环怎么写
一.不带参数的游标for循环 首先编写存储过程的整体结构,如下: create or replace procedure test_proc is v_date date; --变量定义 begin ...
- 使用Spring Data ElasticSearch框架来处理索引
/**步骤:创建工程,导入相应的包--->配置文件---->创建实体类对象------>创建接口---->测试增删改查的方法 **/ //步骤:创建工程,导入相应的包 < ...
- Java poi导出设置 Excel某些单元格不可编辑
小白的总结,大神勿喷:需要转载请说明出处,如果有什么问题,欢迎留言 一.需求: 1.某一列 .某一行或某些单元格不可编辑,其他列可以编辑 二.期间遇到的问题 1.无法设置成不可编辑 2.设置为不可编辑 ...