lintcode-197 排列序号
2017-08-09 00:00
211 查看
原题连接:http://www.lintcode.com/zh-cn/problem/permutation-index/
例如,排列
函数f(int) 用于计算阶乘,position(int[], int)用于返回某个数在其有序数组中的下标。
ps: 如果只是求某个数在其有序数组中的下标,可以使用快排的思想,此时时间复杂度为O(log(n)), 但快排会改变原来数组中数的位置,如果新创建一个数组复制原来的值,则复杂度又会变为O(n).
对于{3,4, 2, 1},先创建一个tag数组,默认值均为0. 然后进入外层for循环。此时内层的for循环由于条件不满足,什么也不做,small = 0(small表示比A[i]小的元素的个数), 只是令tag[0]=1,表示3这个元素已经访问过。然后计算result = result + (position(A, 3) - 0) * f(4 - 0 - 1) = 0 + (2 - 0)*(3!) = 12. 接下来 result = result + (position(A, 4) - 1) * f(4-1-1) = 12 + (3-1)*(2!)=16, result = result + (position(A, 2) - 0) * f(4-2-1)=16+(1-0)*(1!)=17, 最后一个数不需要进行计算,直接加1即可。
其实理解也不难。
(1,2,3,4), (1,2,4,3), (1,3,2,4), (1,3,4,2), (1,4,2,3), (1,4,3,2)
(2,1,3,4), (2,1,4,3), (2,3,1,4), (2,3,4,1), (2,4,1,3), (2,3,3,1)
(3,1,2,4), (3,1,4,2), (3,2,1,4), (3,2,4,1), (3,4,1,2), (3,4,2,1)
.....
对于{3,4,2,1}中的第一个3, 排在它前面的有12个数,也就是使比它小的数的个数2*(A.length-1)! = 12, 对于第二个4,从首位数字为3开始算它的位置。其实就相当于去掉数字3,计算{4,2,1},重复上述步骤。由于3比4小,去掉3后会影响4在{3,4,2,1}中的位置,所以small=1。(如果去掉的第一个数比4大,则不影响其去掉后4在新的有序数组中的位置)。所以(position(A, A[i]) - small) * f(A.length - i - 1)=(3-1)*f(4-1-1)=4, 剩下同理。
排列序号
给出一个不含重复数字的排列,求这些数字的所有排列按字典序排序后该排列的编号。其中,编号从1开始。
样例例如,排列
[1,2,4]是第
1个排列。
/** * @create 2017-08-03 9:57 */ public class Main { public static long permutationIndex(int[] A) { // write your code here int tag[] = new int[A.length]; //0表示没有计算过,1表示已经计算 long result = 0; for (int i = 0; i < A.length - 1; i++) { int small = 0; for (int j = 0; j < A.length; j++) { if (A[j] < A[i] && tag[j] == 1) { small++; } } tag[i] = 1; result = result + (position(A, A[i]) - small) * f(A.length - i - 1); } result++; //最后一位直接加1 return result; } public static long f(int n) { long result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } public static int position(int[] A, int target) { //从0开始 int result = 0; for (int i = 0; i < A.length; i++) { if (A[i] < target) { result++; } } return result; } public static void main(String[] args){ int[] A = {3, 4, 2, 1}; System.out.println(permutationIndex(A)); } }
函数f(int) 用于计算阶乘,position(int[], int)用于返回某个数在其有序数组中的下标。
ps: 如果只是求某个数在其有序数组中的下标,可以使用快排的思想,此时时间复杂度为O(log(n)), 但快排会改变原来数组中数的位置,如果新创建一个数组复制原来的值,则复杂度又会变为O(n).
对于{3,4, 2, 1},先创建一个tag数组,默认值均为0. 然后进入外层for循环。此时内层的for循环由于条件不满足,什么也不做,small = 0(small表示比A[i]小的元素的个数), 只是令tag[0]=1,表示3这个元素已经访问过。然后计算result = result + (position(A, 3) - 0) * f(4 - 0 - 1) = 0 + (2 - 0)*(3!) = 12. 接下来 result = result + (position(A, 4) - 1) * f(4-1-1) = 12 + (3-1)*(2!)=16, result = result + (position(A, 2) - 0) * f(4-2-1)=16+(1-0)*(1!)=17, 最后一个数不需要进行计算,直接加1即可。
其实理解也不难。
(1,2,3,4), (1,2,4,3), (1,3,2,4), (1,3,4,2), (1,4,2,3), (1,4,3,2)
(2,1,3,4), (2,1,4,3), (2,3,1,4), (2,3,4,1), (2,4,1,3), (2,3,3,1)
(3,1,2,4), (3,1,4,2), (3,2,1,4), (3,2,4,1), (3,4,1,2), (3,4,2,1)
.....
对于{3,4,2,1}中的第一个3, 排在它前面的有12个数,也就是使比它小的数的个数2*(A.length-1)! = 12, 对于第二个4,从首位数字为3开始算它的位置。其实就相当于去掉数字3,计算{4,2,1},重复上述步骤。由于3比4小,去掉3后会影响4在{3,4,2,1}中的位置,所以small=1。(如果去掉的第一个数比4大,则不影响其去掉后4在新的有序数组中的位置)。所以(position(A, A[i]) - small) * f(A.length - i - 1)=(3-1)*f(4-1-1)=4, 剩下同理。
相关文章推荐
- python_lintcode_简单题_8旋转字符_420报数_197排列序号
- [LintCode 197] 排列序号(Python)
- lintcode-197-排列序号
- lintcode 容易题:Permutation Index 排列序号
- 排列序号-LintCode
- LintCode:排列序号
- lintcode ----排列序号
- 排列序号II-LintCode
- 197 - 排列序号
- LintCode 197. 排列序号
- Lintcode 排列序号
- LintCode之排列序号
- LintCode-第k个排列
- lintcode 合并排列数组 II
- [LintCode] 全排列
- lintcode-第k个排列-388
- 排列序号
- 康托展开 用于求一个排列的序号或序号对应的排列或对排列的hash
- 算法:康托展开式——实现全排列序列与序号的映射
- lintcode,字符串全排列