k 조합의 빠른 색인 생성


12

나는 얼마 전에 일했던 오래된 문제를 다시 찾고 있습니다.

일반적인 시나리오는 "8 비트 정수 내에 3 비트가 설정 됨", 즉 00000111입니다.

3 개의 세트 비트를 가진 모든 고유 한 조합은 중첩 루프로 쉽게 (순서대로) 생성 할 수 있습니다. 내가 관심이있는 것은 매핑 인덱스 <-> 조합입니다. 즉 "00001011"은 두 번째 조합 (또는 0부터 시작하는 인덱스의 값 "1")입니다.

지금까지 모든 조합을 살펴보고 테이블에 저장하여 조회 색인-> 대화를 O (1) 작업으로 만들었습니다. 다른 방향은 이등분 탐색의 O (ln (n))입니다.

그러나 단점은 도메인을 늘리면 실현할 수없는 수준까지 메모리에 큰 영향을 미친다는 것입니다.

주어진 조합의 n 번째 조합 또는 색인을 계산하는 간단한 방법은 무엇입니까? 조합 순서는 좋지만 필수는 아닙니다.



@MichaelT 귀하의 링크는 문제를 해결하지 못합니다. 조합을 반복하는 것은 문제가되지 않습니다. 이것은 인덱스 및 조합 매핑에 관한 것입니다. "11001000"이 주어지면 인덱스는 무엇입니까? 색인 1673에 속하는 코드는 무엇입니까?
에이코

1
이 경우 OEIS가 유용 할 수 있습니다. 예를 들어, 시퀀스 3,5,6,9,10,12,17,18은 수학 전문 용어에서 "2 비트 온"이라고 말하는 또 다른 방법 인 2의 2 개의 고유 한 힘의 합을 제공합니다 . 다양한 공식은 n 번째 값을 계산하는 다양한 방법을 보여줍니다.

1
8 비트 정수는 저장하기에 사소한 (그리고 영리한 코드보다 적은 공간을 차지하는) 모든 비트 패턴의 256 조합 만 가지고 있습니다. 목표 / 예상 비트 수는 얼마입니까?
9000

1
다른 곳에서 파는 것처럼 이것은 조합 수 시스템 으로 알려져 있으며 Gosper의 핵은 O (1)에서 그것을 할 수 있습니다. 논리는 HACKMEM 175에서 수행되었으며이 블로그 게시물에 설명되어 있습니다 ( 원본 은 매우 간결합니다).

답변:


4

n 번째 조합을 생성하는 것을 "랭킹 해제"알고리즘이라고합니다. 순열과 조합은 종종 문제가 매개 변수화되는 방식으로 동일시 될 수 있습니다. 문제가 무엇인지 정확히 알지 못하면 정확한 올바른 접근 방법을 권장하기가 어렵습니다. 실제로 대부분의 조합 문제의 경우 일반적으로 여러 가지 순위 지정 / 순위 지정 해제 알고리즘이 있습니다.

좋은 자원 중 하나는 Kreher와 Stinson의 "Combinatorial Algorithms"입니다. 이 책에는 많은 좋은 순위와 순위를 정하지 않은 알고리즘이 명확하게 설명되어 있습니다. 더 많은 고급 리소스가 있지만 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;
}

이것은 순열 랭킹이지만 위에서 언급 한 것처럼 조합 랭킹을 동등한 순열 문제로 변환 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.