Given a set of n symbols a size k and a combination of length k of non repeating characters from the symbol set
Given a set of n symbols a size k and a combination of length k of non repeating characters from the symbol set. Write only an ITERATIVE algorithm to print the next unique combination.
Ex: Symbols =[1,2,3,4,5]
size = 3;
given combination = 123, result = 124
given combination = 254, result = 312
Q:
提供一个数字的集合n,然后给一个长度为k的整数(该整数中的数字,都是取自该集合n)。现在要求写一个算法,得到当前整数的“下一个数字”,该整数是比当前整数大的最小整数,并且所有的数字也都是取自集合n。
A: 我的思路是
1. 把当前整数中的所有数字先列出来,如:123 –> A = {1,2,3},然后得到一个剩余数字集合,如B = {4,5}
2. 从右往左扫描整数,如果当前的数字 i 小于B集合中的任意个数字j,则将i和j交换,如把3替换成4
3. 然后把从当前数字i往后的所有数字,替换为集合中的数字(从小到大)
4. 如果碰到i > B中所有的数字,可以把当前的i数字加入到B集合中,继续循环
现在以第二个例子讲解一下
1. A = {2, 5, 4}, B = {1, 3}
2. 扫描
a) 4 > B, 5 > B
b) 2 < B, 所以 2 和 3交换, B = {1,2}, 整数此时变为 354
3. 然后将原来2后面的数字和B中的数字交换(从小到大)5 <-> 1, 4 <-> 2,
所以答案是312
[非正式代码]
1 int n = length(Symbols);
2 int k = length(A);
3 // TRACK WHICH LETTERS ARE STILL AVAILABLE
4 available = sort(Symbols minus A);
5 // SEARCH BACKWARDS FOR AN ENTRY THAT CAN BE INCREASED
6 for (int i=k-1; i>=0; --i) {
7 // LOOK FOR NEXT SMALLEST AVAILABLE LETTER
8 for (int j=0; j<n-k; ++j) {
9 if (A[i] < available[j]) {
10 break;
11 }
12 }
13 if (j < n-k) {
14 // CHANGE A[i] TO THAT, REMOVE IT FROM AVAILABLE
15 int tmp = A[i];
16 A[i] = available[j];
17 available[j] = tmp;
18 // RESET SUBSEQUENT ENTRIES TO SMALLEST AVAILABLE
19 for (j=i+1; i<k; ++j) {
20 A[j] = available[i+1-j];
21 }
22 return A;
23 } else {
24 // A[i] MUST BE LARGER THAN AVAILABLE, SO APPEND TO END
25 available = append(available,A[i]);
26 }
27 }