Permutation Problems
来源:互联网 发布:python 微信告警 编辑:程序博客网 时间:2024/06/05 00:22
What inside a total permutation?
首先逐级分析,给每个permutation标上唯一的索引:
Level 1:
indexinitiation1121...1(n-1)!1(n-1)!+12(n-1)!+22...2(n-1)!+(n-1)2......(k-1)(n-1)!k-1(k-1)(n-1)!+1k(k-1)(n-1)!+2k...k(k-1)(n-1)!+(n-1)!k......(n-1)(n-1)!+1n(n-1)(n-1)!+2n...nn(n-1)!nLevel 2:
indexinitiation(k-1)(n-1)!+1k1(k-1)(n-1)!+2k1...k1(k-1)(n-1)!+(n-2)!k1(k-1)(n-1)!+(n-2)!+1k2(k-1)(n-1)!+(n-2)!+2k2... (k-1)(n-1)!+(n-2)!+(n-2)!k2......(k-1)(n-1)!+(t-1)(n-2)!k(t-1)(k-1)(n-1)!+(t-1)(n-2)!+1kt(k-1)(n-1)!+(t-1)(n-2)!+2kt......(k-1)(n-1)!+(t-1)(n-2)!+(n-2)!kt......(k-1)(n-1)!+(n-1)(n-2)!+1kn(k-1)(n-1)!+(n-1)(n-2)!+2kn......(k-1)(n-1)!+n(n-2)!kn
Level 3:
indexinitiation(k-1)(n-1)!+(t-1)(n-2)!+1kt1(k-1)(n-1)!+(t-1)(n-2)!+2kt1...kt1(k-1)(n-1)!+(t-1)(n-2)!+(n-3)!kt1(k-1)(n-1)!+(t-1)(n-2)!+(n-3)!+1kt2(k-1)(n-1)!+(t-1)(n-2)!+(n-3)!+2kt2......(k-1)(n-1)!+(t-1)(n-2)!+2(n-3)!kt2......(k-1)(n-1)!+(t-1)(n-2)!+(m-1)(n-3)!kt(m-1)(k-1)(n-1)!+(t-1)(n-2)!+(m-1)(n-3)!+1ktm(k-1)(n-1)!+(t-1)(n-2)!+(m-1)(n-3)!+2ktm......(k-1)(n-1)!+(t-1)(n-2)!+m(n-3)!ktm......(k-1)(n-1)!+(t-1)(n-2)!+(n-1)(n-3)!+1ktn(k-1)(n-1)!+(t-1)(n-2)!+(n-1)(n-3)!+2ktn......(k-1)(n-1)!+(t-1)(n-2)!+n(n-3)!ktn
假设我们把n个数存放在数组F[n]中(初始化F[i]=i).
假设我们把n个数存放在数组F[n]中(初始化F[i]=i).
可见索引为K的n位的permutation所对应的第一位是F[ceil(K/(n-1)!)]
纪录下这一位以后我们进入二级子表,在子表中的索引和原索引存在类似求模的关系:
K'= K%(n-1)!==0?(n-1)!: K%(n-1)!
而对应的F' = F.remove(ceil(K/(n-1)!))
接下来重复第一步:可见索引为K的n-1位的permutation所对应的第一位是F'[ceil(K'/(n-2)!)]
按照此过程归纳到F为空,此时K permutation所有位数值已完全纪录。
Solution:
public static String getPermutation(int n, int k) { ArrayList<Integer> f = new ArrayList<Integer>(); for(int i=0;i<n+1;i++) f.add(i); String ret=""; int m = k; for(int lv = 1; lv<=n; lv++){ int b = factorial(n-lv); int a = (int) Math.ceil(m*1.0/b); ret += f.get(a); f.remove(a); if(lv<n){ m = m%b==0?b:m%b; } } return ret; }
What inside a next permutation?
如果序列{a1a2a3...an}已经是非严格降序(字典序),那么这个序列就是最大的序列了。
假如再任给一个序列X={x1x2...xm},将这个序列附在X后面,即Xa1a2a3...an. 令X'={x1x2...x_m-1}, 那么可以得知这个序列是以X'xm所引导的最大序列。
根据字典序的定义,可知对于任意序列{a1a2a3...an}:
X'sort(xm,a1,a2,a3,...,an)<X'xm sort(a1,a2,a3,...,an)<X'xm,a1,a2,a3,...,an<X'xm reverse(sort(a1,a2,a3,...,an))<X'reverse(sort(xm,a1,a2,a3,...,an))
那么,如果{xm,a1,a2,a3,...,an}是非单调的,则X'xm,a1,a2,a3,...,an的下一个序列一定是处于X'sort(xm,a1,a2,a3,...,an) 和 X'reverse(sort(xm,a1,a2,a3,...,an))之间的(包括边界)。因此一切xm之前的序列都可以不予以考虑!
现在分析xm应该和{a1a2a3...an}中的谁置换以确定下一序列的开头元素。首先可以发现,与xm置换的元素不得小于等于xm,否则置换完成以后序列排名无法提升。那么,在所有大于xm的元素中,我们一定是要选择最接近xm的。这样完成的置换可以保证是增幅最小的。
当置换完成后,我们有序列X'ai,a1,a2,a3,...,xm,...,an, 而同样的,对于这个由X' ai所引导的序列存在上下限:
X'ai sort(a1,a2,a3,...,xm,...,an)<X'ai,a1,a2,a3,...,xm,...,an<X'ai reverse(sort(a1,a2,a3,...,xm,...,an))
由之前的分析知:
xm<ai
X'xm,a1,a2,a3,...,an<X'xm reverse(sort(a1,a2,a3,...,an))<X'ai sort(a1,a2,a3,...,xm,...,an)<X'ai,a1,a2,a3,...,xm,...,an
Solution:
public static void nextPermutation(int[] num) { for(int i=num.length-1;i>0;i--){ if(num[i]>num[i-1]){ for(int j=num.length-1;j>=i;j--){ if(num[i-1]<num[j]){ int t = num[j]; num[j] = num[i-1]; num[i-1] = t; /** * a - the array to be sorted * fromIndex - the index of the first element, inclusive, to be sorted * toIndex - the index of the last element, exclusive, to be sorted */ Arrays.sort(num,i,num.length); return; } } } } Arrays.sort(num); }
0 0
- Permutation Problems
- https://leetcode.com/problems/permutation-sequence/
- Problems
- Problems
- Problems
- Permutation
- Permutation
- permutation
- Permutation
- Permutation
- Permutation
- permutation
- Permutation
- permutation
- Permutation
- Permutation
- permutation
- permutation
- 条款21:必须返回对象时,别妄想返回其reference
- C#的委托 Action<>和Func<>
- Android开发AlertDialog使用方法
- 随机数是骗人的,.Net、Java、C为我作证
- Android开发ListView 添加点击事件
- Permutation Problems
- setInterval和setTimeout详解及停止的方法
- JSON-RPC轻量级远程调用协议介绍及使用
- iospfiocozvkhjomfrjxeucvmoxfox
- 推荐系统初探之一 —— 寻找相似的用户
- 推荐系统初探之二 —— 推荐方法
- 缺乏经验的管理者有哪些常犯错误?
- 机器学习相关——协同过滤
- Linux[Centos6.3] 源码编译安装配置 SVN+Apache