การจัดทำดัชนีอย่างรวดเร็วของชุดค่าผสม k


12

ฉันกลับมาทบทวนปัญหาเก่าที่เคยทำมาก่อนหน้านี้แล้ว

สถานการณ์ทั่วไปคือ "3 บิตตั้งอยู่ภายในจำนวนเต็ม 8 บิต" เช่น 00000111

ชุดค่าผสมที่ไม่ซ้ำกันทั้งหมดที่มี 3 ชุดบิตสามารถสร้างได้ง่าย (ตามลำดับ) โดยลูปซ้อนกัน สิ่งที่ฉันสนใจคือชุดค่าดัชนีการแม็พ <-> เช่น "00001011" จะเป็นชุดค่าผสมที่สอง (หรือค่า "1" ในดัชนีแบบ zero-based)

จนถึงตอนนี้ฉันวิ่งผ่านชุดค่าผสมทั้งหมดและเก็บไว้ในตารางทำดัชนีค้นหา -> การสนทนาเป็นการดำเนินการ O (1) อีกทางหนึ่งคือ O (ln (n)) ด้วยการค้นหาแบบแบ่งครึ่ง

ข้อเสียคือความชัดเจนในเรื่องนี้ถ้าเราเพิ่มโดเมนจนถึงจุดที่ไม่สามารถทำได้

อะไรจะเป็นวิธีง่ายๆในการคำนวณชุดค่าผสม n.th หรือดัชนีสำหรับชุดค่าผสมที่กำหนด ลำดับของการรวมกันจะดี แต่ไม่บังคับ



@MichaelT ลิงก์ของคุณไม่ตอบคำถาม - การวนซ้ำชุดค่าผสมไม่ใช่ปัญหา นี่เป็นเรื่องเกี่ยวกับการจับคู่ดัชนีและชุดค่าผสม ได้รับ "11001000" ดัชนีคืออะไร (หรือนับรวมถ้าคุณจะ) รหัสใดเป็นของดัชนี 1673
Eiko

1
อ่าในกรณีนี้คุณอาจพบว่า OEIS มีประโยชน์ ตัวอย่างเช่นลำดับ 3,5,6,9,10,12,17,18 ทำให้เราได้ผลรวมของสองพลังที่แตกต่างกันของสองซึ่งเป็นอีกวิธีหนึ่งในการพูดว่า "สองบิตต่อ" ในศัพท์แสงทางคณิตศาสตร์ สูตรที่หลากหลายแสดงวิธีการคำนวณค่าที่ n

1
จำนวนเต็ม 8 บิตมี 256 บิตของ patters ใด ๆ ที่ไม่สำคัญต่อการจัดเก็บ (และจะใช้พื้นที่น้อยกว่ารหัสที่ฉลาด) บิต / เป้าหมายของคุณมีจำนวนเท่าใด
9000

1
เป็นที่รู้จักกันในชื่อระบบcombinatorial numberและการแฮกของ Gosper สามารถทำได้ใน O (1) ตรรกะได้ทำใน HACKMEM 175 และมีการอธิบายในโพสต์บล็อกนี้ ( เดิมค่อนข้างสั้น)

คำตอบ:


4

การสร้างชุดค่าผสม n-th เรียกว่าอัลกอริทึม "ไม่จัดเรียง" โปรดทราบว่าพีชคณิตและการรวมกันมักจะสามารถบรรจุด้วยวิธีการแก้ไขปัญหาพารามิเตอร์ โดยไม่ทราบว่าปัญหาคืออะไรมันเป็นเรื่องยากที่จะแนะนำวิธีการที่ถูกต้องและในความเป็นจริงสำหรับปัญหาที่เกิดขึ้นกับ combinatoric

ทรัพยากรที่ดีอย่างหนึ่งคือ "Combinatorial Algorithms" โดย Kreher และ Stinson หนังสือเล่มนี้มีอัลกอริทึมการจัดอันดับที่ดีและไม่ได้จัดอันดับไว้อย่างชัดเจน มีทรัพยากรขั้นสูงมากขึ้น แต่ฉันอยากจะแนะนำ Kreher ให้เป็นจุดเริ่มต้น เป็นตัวอย่างของอัลกอริทึม unranking พิจารณาต่อไปนี้:

/** 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.