每天一道LeetCode-----找到第k个排列
Permutation Sequence
原题链接Permutation Sequence
给定n和k,求[1,2,3,...,n]
这个序列的全排列中第k个排列
可以调用k次next_permutation
获取结果,但是next_permutation
内部实现比较慢。
首先考虑能不能确定第k个排列是以哪个数字开头的呢,以[1,2,3,4]
的全排列为例,找第14个排列
- 以1开头的排列总共有3!个,原因是第一个位置是1,剩下3个位置可以随便排列,有6个
- 以2开头的排列总共有3!个,原因是第一个位置是2,剩下3个位置可以随便排列,有6个
- 此时已经有12个排列
- 所以剩下的两个排列即第14个排列一定在以3开头的排列中
用这种方式继续缩减数量,以3开头的排列中最小的为[3,1,2,4]
,3已经固定,那么就找[1,2,4]
的全排列的第2个排列,就是整个排列的第14个排列
- 以1开头的排列共有2!个,原因是第二个位置是1,剩下2个位置可以随便排列,有2个
- 此时已经有两个排列,可以确定结果一定在以
[3,1]
开头的排列中,即[3,1,2,4]
或[3,1,4,2]
继续缩减数量,以[3,1]
开头的排列中最下的为[3,1,2,4]
,[3,1]
已经固定,那么就找[2,4]的全排列的第2个排列,就是[1,2,4]的全排列的第2个排列,也就是整个排列的第14个排列
- 以2开头的排列共有1!个,原因是第三个位置是2,剩下一个位置给4,有1个
- 以4开头的排列共有1!个,原因是第三个位置是4,剩下一个位置给12,有1个
- 此时已经有两个排列,可以确定结果是以4开头的排列,即
[4,2]
,所以结果为[3,1,4,2]
所以,可以每次确定一个大范围,在大范围的基础上进一步缩小范围,直到最后只有一个数字为止。遍历n遍即可。
假设某次需要找到第k个排列(k从1开始),以第i个位置开头(i从1开始),上述过程可以表示为
要找的排列的开头是所剩数字中的第k / (n-i)!个 (整除)或第k / (n-i)! + 1个(非整除)数字,(从1开始)
原因
上述第一步,序列为[1,2,3,4],k为14,i为1,(n-i)!为6,k / (n-i)!为2,此时因为要找第14个排列(从1开始),以1,2开头的各占6个,所以在以3开头的排列中找,所以应该是k / (n-i)! + 1(非整除),即第3个数字,从1开始,为3
上述第二步,序列为[1,2,3],确定以3开头后,k为2,i为2,(n-i)!为2,k / (n-i)!为1,此时因为要找第2个排列,以1开头的就有2个,所以在以1开头的排列中找,所以应该是k / (n-i)! (整除),即第1个数字,从1开始,为1
上面需要根据情况讨论的原因是位置索引都是从1开始的,如果索引从0开始,那么就不会有这么多问题,此时k为14,即要找第13个排列(从0开始)
上述第一步,序列为[1,2,3,4],k为13,i为1,(n-i)!为6,k / (n-i)!为2,k / (n-i)!为2,即第2个数字(从0开始),为3
上述第二步,序列为[1,2,3],确定以3开头后,k为1,i为2,(n-i)!为2,k / (n-i)!为0,即第0个数字,为1
代码如下
class Solution {
public:string getPermutation(int n, int k) {vector<int> factorial(n+1, 1);for(int i = 2; i <=n; ++i)factorial[i] = i * factorial[i - 1];vector<int> nums;for(int i = 1; i <= n; ++i)nums.emplace_back(i);string res("");for(int i = 1; i <= n; ++i){/* 找开始点 */int index = k / factorial[n - i];/* 如果非整除,加一 */if(k % factorial[n - i] != 0)++index;res += (nums[index - 1] + '0');nums.erase(nums.begin() + index - 1);k = k - ((index - 1) * factorial[n - i]);}return res;}
};
每天一道LeetCode-----找到第k个排列相关推荐
- LeetCode —— 60. 第k个排列(Python3)
给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123" "132&qu ...
- LeetCode 60. 第k个排列(回溯 康托展开)
文章目录 1. 题目 2. 解题 2.1 回溯 2.2 数学-康托展开 1. 题目 给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = ...
- LeetCode 中级 - 第k个排列(60)
可以用数学的方法来解, 因为数字都是从1开始的连续自然数, 排列出现的次序可以推算出来, 对于n=4, k=15 找到k=15排列的过程:1 + 对2,3,4的全排列 (3!个) 2 + 对1,3,4 ...
- LeetCode 60. 第k个排列(python、c++)
题目描述 给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123" "1 ...
- leetcode60.第k个排列java题解
LeetCode 60.第k个排列 给出集合 [1,2,3,-,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: 1. "1 ...
- Leetcode算法Java全解答--60. 第k个排列
Leetcode算法Java全解答–60. 第k个排列 文章目录 Leetcode算法Java全解答--60. 第k个排列 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 其他 题目 ...
- 一天一道LeetCode(61-90)
一天一道LeetCode(61-90) 文章目录 一天一道LeetCode(61-90) 61.旋转链表 62.不同路径 63.不同路径 II 64.最小路径和 65.有效数字(未解决) 66.加一 ...
- 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- 每日一道 LeetCode (16):求 x 的平方根
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
最新文章
- 2022-2028年中国铁路信息化建设投资分析及前景预测报告
- Vue——项目部署到非根目录下的解决方案
- CSP2021NOIP2021游记
- 【ECharts系列|02可视化大屏】 舆情分析,人口分析及警情警力活动情况的实现【下篇】
- 字符串对象的各种方法
- jeewms仓库管理系统源码
- 思考…求知(double和Double的区别)
- mysql查询当天数据(上周、本月、上个月、距离当前现在6个月的数据)
- 【Oracle】查看用户的信息(状态、默认表空间等)
- c语言 电脑 控制串口,PC与单片机RS-232串口的通讯和控制
- 微信小程序挑战赛:全校级人脸门禁系统
- PhalApi 事务操作
- 百度富文本编辑器插入视频链接相关问题
- OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体
- Excel2003 找回工作表密码方法
- PHP 微信JSP支付
- 【bzoj 1340】 Escape逃跑问题 【Baltic2007】
- 智能打印SDK---官方博客
- IIS的404页面乱码:鏃犳硶鏄剧ず椤甸潰锛屽洜涓哄彂鐢熷唴閮ㄦ湇鍔″櫒閿欒銆�的解决方法
- win10远程桌面_Win10 远程桌面及防火墙设置,让自带远程更安全
热门文章
- DevExpress WPF v18.2新版亮点(四)
- bzoj1110: [POI2007]砝码Odw
- DWR第六篇之文件下载
- mysql 多数据源多主一从复制
- javascript 高级程序设计学习笔记(面向对象的程序设计) 1
- lightoj 1004 dp:数字三角形
- 一步一步深入spring(1)--搭建和测试spring的开发环境
- VoIP协议标准浅析
- 解决问题 “You don't have permission to access /index.html on this server.”
- [网络安全自学篇] 十一.虚拟机VMware+Kali安装入门及Sqlmap普及