leetcode_060 Permutation Sequence
2016-03-26 21:05
429 查看
题意分析:1~n组成的序列从小到大排序,按顺序找出k个序列,并输出。
解题思路:
对于数值n,排列组合共有n!种排列。
第一位每个数组开头的序列有(n-1)!个序列,
依此类推,第二位每一个数开头有(n-2)!个序列。
因数字不重复,故用sign标记数字是否使用过,data存阶层的数,每次循环找到没有使用的数中第
k/data[i]个数就是当前位的数字。
其详细过程见程序中注释。
解题思路:
对于数值n,排列组合共有n!种排列。
第一位每个数组开头的序列有(n-1)!个序列,
依此类推,第二位每一个数开头有(n-2)!个序列。
因数字不重复,故用sign标记数字是否使用过,data存阶层的数,每次循环找到没有使用的数中第
k/data[i]个数就是当前位的数字。
其详细过程见程序中注释。
class Solution { public: // 利用库函数实现(超时) string getPermutation(int n, int k) { string str = string("123456789").substr(0, n); for(int i = 1; i <= k-1; i++) next_permutation(str.begin(), str.end()); return str; } // 递归实现(超时) string getPermutation(int n, int k) { string result; vector<int> nums; for (int i = 1; i <= n; i++) nums.push_back(i); for(int i = 1; i <= k-1; i++) nextPermutation(nums); for (int i = 0; i < nums.size(); i++) { result += nums[i] + '0'; } return result; } void myswap(int &x, int &y) { int t; t = x; x = y; y = x; } void nextPermutation(vector<int> &nums) { int n = nums.size(); if (n == 1) return; for (int i = n - 2, j = n - 1; i >= 0; i--, j--) { //执行第一步,从后向前,找第一个不满足递增的数nums[i] if (nums[i] < nums[j]) { int k = n - 1; //执行第二步,从后向前,找第一个比nums[i]大的数nums[k] while (nums[k] <= nums[i]) k--; //执行第三步,交换两个数nums[i]和num[k] swap(nums[i], nums[k]); //执行第四步,对nums[i] 后面的数进行翻转 reverse(nums.begin() + j, nums.end()); return ; } } //当没第一步未找到合适的数,则对整个进行翻转 reverse(nums.begin(), nums.end()); } // 上面超时的原因是算法都是逐个求排列,下面利用非逐个求,而是直接构造第k个排列。以n=4,k=17为例,数组src=[1,2,3,...]。 // 计算第17个排列的第一个数。首先直到(n-1)!=3!=6,即以1和2开头的排列总共有6*2=12个<17,故第17个排列的第一个数不可能为 // 1或者2,6*3>17,故第17个排列第一个数为3。即第17个排列的第一数是原数组(原数组有序)的第m=upper(17/6)=3个数。第一个 // 数固定后,从src数组中删除概述,相当于在当前src的基础上求k-(m-1)*(n-1)!=17-2*6=5个排列,在递归求解。 string getPermutation(int n, int k) { string str = string("123456789").substr(0, n); string result(n, ' '); for (int i = 0; i < n; i++) { result[i] = helper(str, k); } return result; } // 以s中字符构造全排列中,返回第k个排列的第一个字符,并删除s中该字符,s中字符递增有序 char helper(string &s, int &k) { int tmp = factorial(s.size() - 1); int i = (k - 1) / tmp; char res = s[i]; s.erase(i, 1); k -= i * tmp; // 更新k return res; } int factorial(int n) { int res = 1; for (int i = 2; i <= n; i++) res *= i; return res; } // 上面算法的非递归实现(未超时) string getPermutation(int n, int k) { int total = factorial(n); string candidate = string("123456789").substr(0, n); string res(n, ' '); for (int i = 0; i < n; i++) // 依次计算排列的每个位 { total /= (n - i); int index = (k - 1) / total; res[i] = candidate[index]; candidate.erase(index, 1); k -= index * total; } return res; } int factorial(int n) { int res = 1; for (int i = 2; i <= n; i++) { res *= i; } return res; } // 整体思路:先初始化字符串"1,2,...,n",然后从0位开始逐步确定每一位的数字,第i位后面的数字有(n-1-i)!种排法,若假设k<(n-1-i)!,则 // 可确定第i位的数字。 string getPermutation(int n, int k) { // 初始化字符串"1...n" int Kn = 1; string res(n, '1'); for (int i = 2; i <= n; i++) { Kn *= i; res[i - 1] = i + '0'; } int temp = n; for (int i = 0; i < res.size(); i++) { Kn /= temp; for (int j = i + 1; j < n && k > Kn; j++) { swap(res[i], res[j]); k -= Kn; if (k == 1) break; } temp--; } return res; } // 非递归实现(未超时) string getPermutation(int n, int k) { int i; int j; int data[10]; int sign[10]; data[1] = 1; for (i = 2; i <= n; i++) { data[i] = data[i - 1] * i; } for (int i = 0; i < 10; i++) { sign[i] = 0; } string s = ""; i = i - 2; k--; while (i >= 0) { int temp = k / data[i]; for (j = 1; j < 10; j++) { if (sign[j] == 0) temp--; if (temp < 0) break; } sign[j] = 1; s += j + '0'; k %= data[i]; i--; } return s; } };
相关文章推荐
- java中PriorityQueue优先级队列使用方法
- POJ 3061 Subsequence(尺取法)
- easyui前台改变datagrid某单元格的值
- Range minimum query
- StringBuilder、StringBuffer和String三者的联系和区别
- ElasticSearch中根据查询结果删除数据(delete by query)
- 我的Android进阶之旅------>android如何将List<NameValuePair>请求参数列表转换为json格式
- CodeForces-626A-Robot Sequence
- UVA 1252(p287)----Twenty Questions
- POJ2524Ubiquitous Religions
- 如何降低Vue.js项目中Webpack打包文件的大小?
- 334. Increasing Triplet Subsequence
- 通过request获得全路径
- 自定义控件基础 requestLayout()和invalidate()区别
- 五、初学servlet之请求Request
- Leetcode Sudoku Solver My Submissions Question
- 开源的OLAP框架druid
- 有多个手势支持时候需要实现UIGuestrueRecoginer方法
- UIBezierPath转换为传统上下文的样式
- UIGestureRecognizer手势有哪些