如何计算整数中递归地与给定数字相加的数字对

Posted

技术标签:

【中文标题】如何计算整数中递归地与给定数字相加的数字对【英文标题】:How can I count the pairs of digits within an integer that sum to a given number recursively 【发布时间】:2020-11-24 17:00:35 【问题描述】:

这是我需要做的:

编写1个函数,传递1个参数(给定的数字)

只使用递归

返回总和为 10 的数字对的数量

例如,如果参数是 734655,那么它应该返回 3,因为 7+3、4+6 和 5+5 是 3 总和为 10 的对

我得出的结论是:

从第 1 位开始,检查其余所有数字,然后转到第 2 位,检查第 3.... 最后一位数字。 基本情况是 current_index 到达最后一位/

使用循环很容易解决,而我被要求使用递归,我真的很困惑我应该在每次调用中做什么,或者在另一个递归中是否会有递归......

【问题讨论】:

【参考方案1】:

解决这个问题的一种方法是递归地对位数进行操作。对于存在的数字 x(具有正数),检查是否还有一些 y 使得 x + y 等于指定的总数(例如,10)。如果y 存在(具有正数),则返回1 加上剩余数字中递归计算的对数,不包括xy。如果不是,则返回剩余数字中递归计算的对数,不包括x。当没有剩余数字时,基本情况返回0

这是 Python 中的示例实现。 pair_present 是一个布尔值,但在用于求和时会转换为整数(1 用于True0 用于False)。 num_pairs 是作为纯函数编写的,因此它的参数不会被破坏性地修改。

from collections import Counter

def num_pairs(digits, total=10):
    try:
        x = next(digits.elements())
    except StopIteration:
        # base case: no digits
        return 0
    digits = digits - Counter(x: 1)
    y = total - x
    pair_present = digits[y] > 0
    digits = digits - Counter(y: 1)
    return pair_present + num_pairs(digits, total=total)

number = 734655
digits = Counter(int(c) for c in str(number))
print(num_pairs(digits))  # 3

类似的方法可以直接对数字的字符串表示进行操作,而不是对数字计数。对于数字中的第一个数字x,检查是否还有一些y 使得x + y 等于指定的总数(例如,10)。如果y 存在,则返回1 加上剩余字符串中递归计算的对数,不包括xy。如果不是,则返回剩余字符串中递归计算的不带x 的对数。当没有剩余数字时,基本情况返回0

这是 Python 中的示例实现。

def num_pairs(string, total=10):
    if len(string) == 0:
        return 0
    x = int(string[0])
    string = string[1:]  # remove x from string
    y = total - x
    pair_present = str(y) in string
    if pair_present:
        string = string.replace(str(y), '')  # remove y from string
    return pair_present + num_pairs(string, total=total)

number = 734655
print(num_pairs(str(number)))  # 3

与上述方法相比,以下迭代方法具有以下优点:1)它将数字本身作为输入,2)避免在早期解决方案中复制对象(早期用于避免对输入的破坏性修改),以及3) 似乎是一种更直接的解决问题的方法。

from collections import Counter

def num_pairs(number, total=10):
    digits = Counter(int(c) for c in str(number))
    output = 0
    while True:
        x = next(digits.elements(), None)
        if x is None:
            return output
        digits[x] -= 1
        y = total - x
        if digits[y] > 0:
            output += 1
            digits[y] -= 1

print(num_pairs(734655))  # 3

递归解决问题的另一种方法是将前面的迭代实现转换为使用递归代替循环的实现,如下面的 Python 实现示例所示。一些语言(例如,Scheme)会在这里使用尾调用优化,这样每个递归调用都不会使用任何额外的堆栈空间。这不是 Python 的情况。

from collections import Counter

def num_pairs(number, total=10, _state=None):
    if _state is None:
        _state = 
            'digits': Counter(int(c) for c in str(number)),
            'result': 0
        
    digits = _state['digits']
    x = next(digits.elements(), None)
    if x is None:
        return _state['result']
    digits[x] -= 1
    y = total - x
    if digits[y] > 0:
        _state['result'] += 1
        digits[y] -= 1
    return num_pairs(number, total, _state)

print(num_pairs(734655))  # 3

此外,递归解决方案可以利用排序和二进制搜索。首先,对数字进行排序。对于第一个数字x,对其他数字使用二进制搜索来查看是否存在y,使得x + y 等于指定的总数。如果存在y,则返回 1 加上剩余排序数字中递归计算的对数。如果不是,则返回剩余数字中递归计算的对数。当没有剩余数字时,基本情况返回 0。对于x + y 等于指定总数 x == y 的情况,需要特殊情况处理,以防止过度计数。这是 Python 中的示例实现。

from bisect import bisect_left

def num_pairs(digits, total=10, _sorted=False):
    if len(digits) == 1:
        return 0
    if not _sorted:
        digits = sorted(digits)
    x = digits[0]
    digits = digits[1:]
    y = total - x
    if x > y:
        return 0
    # Use binary search to check for y's location.
    idx = bisect_left(digits, y)
    pair_present = idx < len(digits) and digits[idx] == y
    # If x + y == total and x == y, pop y to prevent over-counting.
    if pair_present and x == y:
        digits = digits[1:]
    return pair_present + num_pairs(digits, total=total, _sorted=True)

number = 734655
print(num_pairs([int(c) for c in str(number)]))  # 3

【讨论】:

以上是关于如何计算整数中递归地与给定数字相加的数字对的主要内容,如果未能解决你的问题,请参考以下文章

没有正确数字的递归数字总和

python如何递增相加一个数字,比如25-200的全部数字?

使用递归搜索整数数组中元素的所有组合

递归实现:从给定的字典中抽出所有相加值SUM的全部组合

Python笔试题:给定一个非负整数num,反复将各个位上的数字相加,直到结果为一位数杭州多测师杭州多测师_王sir

LeetCode答题记录233. 数字1的个数