【问题标题】:How to print all the possible combinations of a N digit number without using arrays?如何在不使用数组的情况下打印 N 位数字的所有可能组合?
【发布时间】:2015-06-06 15:09:22
【问题描述】:

我强调的是不使用数组。这有什么数学推导吗?

【问题讨论】:

  • 数组只是存储数据的内存空间,为什么要这么做?
  • “所有可能的组合”是什么意思?你的意思是像数字的字谜?您是在寻找伪代码还是某种特定语言?
  • 您输入的是 N 位数字吗?它可能有重复的数字吗?
  • @ryanyuyu 我标记算法...
  • @PhamTrung 如何在不使用数组的情况下生成数字 123 的所有排列/组合。是的,它是一个存储 DS,但它提供了一种方便的算法机制来解决许多问题,因为我们可以轻松地操纵每个数字具有简单的索引机制。

标签: arrays algorithm combinations combinatorics


【解决方案1】:

您可以使用"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
}

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

这是做什么的:

  1. 使用组合的两种不同表示形式 a) 作为选择和 b) 作为二进制数
  2. 使用gray coding(或最小变化编码)从一个组合(二进制数)移动到下一个组合(二进制数),在二进制表示中保持相同数量的ones
  3. 最终所有组合都以这种方式生成(但不是按字典顺序

有关组合的更多数论表示,请参阅Combinatorial number system,它将组合表示为整数,即从组合到整数的双射(如果您想在不明确使用数组的情况下使用严格的算术)

【讨论】:

    【解决方案2】:

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

    以下 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)
    

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

    【讨论】:

      猜你喜欢
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      相关资源
      最近更新 更多