如何在不使用数组的情况下打印N位数的所有可能组合?

时间:2015-06-06 15:09:22

标签: arrays algorithm combinations combinatorics

我强调不使用数组。是否有任何数学推导?

2 个答案:

答案 0 :(得分:0)

您可以使用"Gosper's hack"操纵二进制数字,但是您可以根据您可以生成/表示这种方式的组合大小来限制机器的字长。

// find next k-combination
bool next_combination(unsigned long& x) // assume x has form x'01^a10^b in binary
{
  unsigned long u = x & -x; // extract rightmost bit 1; u =  0'00^a10^b
  unsigned long v = u + x; // set last non-trailing bit 0, and clear to the right; v=x'10^a00^b
  if (v==0) // then overflow in v, or x==0
    return false; // signal that next k-combination cannot be represented
  x = v +(((v^x)/u)>>2); // v^x = 0'11^a10^b, (v^x)/u = 0'0^b1^{a+2}, and x ← x'100^b1^a
  return true; // successful completion
}

使用第一个x初始化k - 组合即x = (1L<<k) - 1Lk one已设置)

这是做什么的:

  1. 使用组合a)的两种不同表示作为选择,b)作为二进制数
  2. 使用gray coding(或最小更改编码)从一个组合(二进制数)移动到下一个组合(二进制数),在二进制表示中保持相同数量的one s
  3. 最终所有组合都以这种方式生成(但不是lexicographicaly
  4. 对于组合的更多数论 - 表示,请参阅Combinatorial number system表示组合为整数,即从组合到整数的双射(如果要在不使用数组的情况下严格使用算术)明确地)

答案 1 :(得分:0)

十进制整数本质上是一个数字数组。一些简单的数学运算将允许对整数中的那些数字进行索引,就像任何其他数组一样。

以下python示例代码将通过利用这一事实完全符合您的要求:

#!/usr/bin/python3

def getNumDigits(number):
    if number == 0:
        digits = 1
    else:
        digits = 0
        while number > 0:
            digits += 1
            number //= 10
    return digits

def getDigitAtPosition(position, number):
    return (number // (10**position)) % 10

def swapDigits(number, position_one, position_two):
    digit_one = getDigitAtPosition(position_one, number)
    digit_two = getDigitAtPosition(position_two, number)
    difference = digit_one - digit_two
    return number + (difference * 10**position_two) - (difference * 10**position_one)

def sortNumber(number, num_digits=None):
    if num_digits is None:
        num_digits = getNumDigits(number)
    for i in range(num_digits-1):
        for j in range(i+1, num_digits):
            if getDigitAtPosition(j, number) < getDigitAtPosition(i, number):
                number = swapDigits(number, i, j)
    return number

def isDigitInNumber(digit, number):
    for i in range(getNumDigits(number)):
        if getDigitAtPosition(i, number) == digit:
            return True
    return False

def printCombinations_sorted(number, prepend, num_digits):
    if num_digits == 1:
        print(number + (prepend * (10**num_digits)))
    else:
        lead_position = num_digits-1
        lead_digit = getDigitAtPosition(lead_position, number)
        digits_swapped = lead_digit
        printCombinations_sorted(number % 10**(lead_position), (prepend*10) + lead_digit, num_digits-1)
        for i in range(num_digits-1):
            sub_number = swapDigits(number, num_digits-1, num_digits-2-i)
            sub_lead_digit = getDigitAtPosition(lead_position, sub_number)
            if not isDigitInNumber(sub_lead_digit, digits_swapped):
                digits_swapped = digits_swapped*10 + sub_lead_digit
                printCombinations_sorted(sub_number % 10**(lead_position), (prepend*10) + sub_lead_digit, num_digits-1)

def printCombinations(number):
    num_digits = getNumDigits(number)
    number = sortNumber(number, num_digits)
    printCombinations_sorted(number, 0, num_digits)

if __name__ == "__main__":
    number = 101010
    printCombinations(number)

由于没有指定是否允许重复数字,我写这个假设它们会。如果不是这样的话,可以简化一下。