[LeetCode] “全排列”问题系列(二) - 基于全排列本身的问题,例题: Next Permutation , Permutation Sequence
一、开篇
既上一篇<交换法生成全排列及其应用> 后,这里讲的是基于全排列 (Permutation)本身的一些问题,包括:求下一个全排列(Next Permutation);求指定位置的全排列(Permutation Sequence);给出一个全排列,求其所在位置。
二、例题
1. 求下一个全排列,Next permuation
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.1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1
class Solution {
public:
void nextPermutation(vector<int> &num) {
}
};
题目的意思是假设所有的全排列按照字典顺序被排列,找给定全排列的下一个。
我的思路是:所谓下一个全排列,其实就是将当前vetor的一个子集重排而已。这个子集如何划分?
考虑排列1237456,它的下一个排列是1243567,找子集的方法其实就是:从头到尾找到最后一个满足 num[i+1] > num[i] 的一对(实现时可以从尾到头遍历,找到第一个num[i+1] > num[i] 的一对),需要重排的子集就是 num[i~size-1] 这个子集。这个子集num[i~size-1] 满足一个条件:前两个元素递增,后面都是递减或者后面已经没有元素。特殊情况是:如果找不到这样的存在递增关系的 num[i] 和 num[i+1],说明整个序列都是降序,也就是没有更大的排列了,根据题目要求,直接将序列逆序即可。
重新排列的方式就是从num[i+1 ~ size-1]中选一个比num[i] 大的最小元素,将其和num[i] 交换,然后将num[+1 ~ size-1]逆序。
代码:
class Solution {
public:
void nextPermutation(vector<int> &num) {
int size = num.size();
if(size == || size == ) return;
int ascHead = size - ; //最后一个num[i] < num[i+1] 的 i
for(; ascHead >= && num[ascHead] >= num[ascHead + ]; --ascHead);
if(ascHead < ){reverse(num, , size-); return;}
int insert = size - ; //存储那个比num[ascHead]大的最小值的index
for(; insert > ascHead && num[insert] <= num[ascHead]; --insert);
swap(num, ascHead, insert);
reverse(num, ascHead+, size-);
}
private:
void swap(vector<int> &num, int left, int right){
int temp = num[left];
num[left] = num[right];
num[right] = temp;
}
void reverse(vector<int> &num, int start, int end){
while(start < end){
swap(num, start++, end--);
}
}
};
2. 给一个全排列,求其在所有全排列中位于第几位
这道题上LeetCode上没有例题。
例如给定一个排列 356421, 因为第一位为3,因此1 和 2 开头的全排列已经经过了,以1开头的全排列个数为5!,2也是。因此该全排列的排名 > 2 * 5!
第二位为5,对于以3开头的全排列,排在35前面的有31,32,34开头的三个全排列。在356421中,5右边比5小的也正是1,2,4。
我们可以发现:序列长度为n,对于给定排列P某位上的数,假设这个数在P上从右起排第m位,我们只要看看该数右侧的位数上还有几个比它小的,就知道该数以右的部分在对应所有子序列中的排名了。
因此P的总排名 = ∑k*m! (m从0到n-1,k表示第m+1位之后有多少小于第m+1位个数。
3. 求指定位置的全排列
Permutation Sequence
The set [1,2,3,…,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123""132""213""231""312""321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive
class Solution {
public:
string getPermutation(int n, int k) {
}
};
有了上一题的思路,这一題就很容易了。
无非就是不断除以m!,m在递减,将余数作为分母继续循环。
class Solution {
public:
string getPermutation(int n, int k) {
bool dig[n];
unsigned int mul = ;
int j = , ind = , i = ;
string res = "";
for(i = ; i < n; mul *= (i>?i:), dig[i] = false, ++i);
--k; //将k偏移,将0作为第一位
for(i = n; i > ; --i, k %= mul, mul /= (i>?i:)){
ind = k/mul;
for(j = ; j < n; ++j){
if(!dig[j]) --ind;
if(ind < ) break;
}
dig[j] = true;
res.push_back(j + ''); //这里j从0开始算,因此转化成字符要+'1'
}
return res;
}
};
三、总结:
基于全排列本身可以出不少题目,但是我们只要知道全排列的数量是按照 k! 计算的,就可以从这里入手。
如果想构造全排列,上一文中的交换法就是一个思路
[LeetCode] “全排列”问题系列(二) - 基于全排列本身的问题,例题: Next Permutation , Permutation Sequence的更多相关文章
- Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401开发
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式SD卡TF卡读写
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Keil MDK STM32系列(四) 基于抽象外设库HAL的STM32F401开发
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Keil MDK STM32系列(六) 基于抽象外设库HAL的ADC模数转换
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Leetcode之回溯法专题-47. 全排列 II(Permutations II)
Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Leetcode之回溯法专题-46. 全排列(Permutations)
Leetcode之回溯法专题-46. 全排列(Permutations) 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3, ...
随机推荐
- Windows 服务器开通防火墙后,IISFTP和Serv U开通的FTP账号不能登录
应广大服务器客户要求一至反应Windows 服务器开通防火墙后,IISFTP和Serv U开通的FTP账号不能登录,出现列表超时的情况,特提供以下解决方案: 1. IIS FTP用户解决方法: 在防火 ...
- 理解Javascript的异步等待
目前async / await特性并没有被添加到ES2016标准中,但不代表这些特性将来不会被加入到Javascript中.在我写这篇文章时,它已经到达第三版草案,并且正迅速的发展中.这些特性已经被I ...
- 浅析JVM中的GC日志
目录 一.GC日志的格式分析 二.运行时开启GC日志 一.GC日志的格式分析 在讲述GC日志之前,我们先来运行下面这段代码 package com.example; public class Test ...
- 题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)?
题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)? //一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米 doub ...
- Android兼容包multidex的开发和构建方法
在Android开发中,函数方法超过65k限制后,我们就常常会用到multidex分包解决,但是multidex的配置,对系统apk的构建.签名.打包复杂性大大的增加,严重的降低了构建效率.那这个问题 ...
- dubbo 管理控制台 的安装 dubbo-admin
按照官方文档来,只是官方文档中提供的war包无法下载,我的环境至少是这样,不知道其他网络环境是否OK. war包下载地址:链接: http://pan.baidu.com/s/1i32fs7j 密码: ...
- 互联网的寒冬来了,BAT都不社招了
一 总理上次来到创业街,是四个月,要不就是五个月前了. 之后,全国创业形势一路走红,锣鼓喧天鞭炮齐鸣.大众创业万众创新,颇有大炼钢铁亩产万斤之势,尤其在媒体上. 再之后,2015 进入下半年,风投圈的 ...
- android 6.0权限判断 音频 拍照 相册
------------------------------------------打开音频权限------------------------------------------------ if ...
- 如何在IIS7下配置ASP+ACCESS环境
如何在IIS7下配置ASP+ACCESS环境 | 浏览:901 | 更新:2013-01-16 17:46 1 2 3 4 5 6 7 分步阅读 默认装完IIS7之后,使用ASP程序会发现提示数据库连 ...
- 用飞信监控GoldenGate进程
监控GoldenGate进程 1) 在goldengate安装目录下建立文件ogginfo $vim ogginfo info all 2) 配置飞信报警 ...