生成第n个组合称为“不排序”算法。请注意,排列和组合通常可以等同于问题的参数化方式。在不确切知道问题是什么的情况下,很难推荐正确正确的方法,并且实际上,对于大多数组合问题,通常可能有几种不同的排序/不排序算法。
一种很好的资源是Kreher和Stinson的“组合算法”。本书有许多很好的排名和排名算法,这些算法已经清楚地说明了。有更多高级资源,但是我建议您以Kreher作为起点。作为取消排序算法的示例,请考虑以下内容:
/** PKSUL : permutation given its rank, the slots and the total number of items
* A combinatorial ranking is number of the permutation when sorted in lexicographical order
* Example: given the set { 1, 2, 3, 4 } the ctItems is 4, if the slot count is 3 we have:
* 1: 123 7: 213 13: 312 19: 412
* 2: 124 8: 214 14: 314 20: 413
* 3: 132 9: 231 15: 321 21: 421
* 4: 134 10: 234 16: 324 22: 423
* 5: 142 11: 241 17: 341 23: 431
* 6: 143 12: 243 18: 342 24: 432
* From this we can see that the rank of { 2, 4, 1 } is 11, for example. To unrank the value of 11:
* unrank( 11 ) = { 11 % (slots - digit_place)!, unrank( remainder ) }
* @param rank the one-based rank of the permutation
* @param ctItems the total number of items in the set
* @param ctSlots the number of slots into which the permuations are generated
* @param zOneBased whether the permutation array is one-based or zero-based
* @return zero- or one-based array containing the permutation out of the set { ctItems, 1,...,ctItems }
*/
public static int[] pksul( final int rank, final int ctItems, final int ctSlots, boolean zOneBased ){
if( ctSlots <= 0 || ctItems <= 0 || rank <= 0 ) return null;
long iFactorial = factorial_long( ctItems - 1 ) / factorial_long( ctItems - ctSlots );
int lenPermutation = zOneBased ? ctSlots + 1 : ctSlots;
int[] permutation = new int[ lenPermutation ];
int[] listItemsRemaining = new int[ ctItems + 1 ];
for( int xItem = 1; xItem <= ctItems; xItem++ ) listItemsRemaining[xItem] = xItem;
int iRemainder = rank - 1;
int xSlot = 1;
while( true ){
int iOrder = (int)( iRemainder / iFactorial ) + 1;
iRemainder = (int)( iRemainder % iFactorial );
int iPlaceValue = listItemsRemaining[ iOrder ];
if( zOneBased ){
permutation[xSlot] = iPlaceValue;
} else {
permutation[xSlot - 1] = iPlaceValue;
}
for( int xItem = iOrder; xItem < ctItems; xItem++ ) listItemsRemaining[xItem] = listItemsRemaining[xItem + 1]; // shift remaining items to the left
if( xSlot == ctSlots ) break;
iFactorial /= ( ctItems - xSlot );
xSlot++;
}
if( zOneBased ) permutation[0] = ctSlots;
return permutation;
}
这是置换排序,但是如上所述,在许多情况下,您可以将组合排序转换为等效的置换问题。