青训营X豆包MarsCode 技术训练营递归法 | 豆包MarsCode AI 刷题

69 阅读3分钟

递归法解题

最少步数归零问题
1.问题描述

小R拿到了一个长度为n的数组,其中每个元素都是一个正整数。小R发现每次可以删除某个数组中某个数的一位数字,这样可以逐步将所有数字变为0。他想知道,要将数组中所有数字都变为0,最少需要多少步?

例如:对于数字 103,小R可以选择删除第1位数字,将其变为 3;或者删除第2位数字,变为 13,又或者删除第3位数字,将其变为 10。最终目标是将所有数字都删除为0。

2.测试样例

样例1:

输入:n = 5,a = [10, 13, 22, 100, 30]
输出:7

样例2:

输入:n = 3,a = [5, 50, 505]
输出:4

样例3:

输入:n = 4,a = [1000, 1, 10, 100]
输出:4

3.题目思路

通过递归深度优先搜索的方式,对每个数字尝试所有可能的删除位操作,计算出将每个数字变为0所需的最少步数,并将这些步数累加,以得到将数组中所有数字变为0所需的总最少步数。

4.详细方法

deleteSteps 函数:

  • 基本情况:

如果 num 为 0,则不需要任何步骤,返回 0。 如果 num 是一位数,那么只需要一步就可以将其变为 0,返回 1。

  • 递归情况:

对于每一位数字,我们考虑删除该位数字后的情况。将 num 转换为字符串 num_str,以便可以操作每一位数字。遍历 num_str 的每一位数字,对于当前索引 i,我们构造一个新的数字 new_num,它是删除了第 i 位数字后的数字。

  • 递归调用:

对于每个 new_num,我们递归地调用 deleteSteps 函数,计算将其变为 0 所需的最少步数。

  • 结果更新:

我们维护一个变量 res,初始值为正无穷大 float('inf'),表示当前找到的最小步数。对于每个 new_num,我们计算删除当前位数字后,剩余数字变为 0 所需的最少步数,并更新 res 为当前找到的最小值。

  • 返回结果:

最后,返回 res + 1,因为当前位数字也被删除了,所以需要额外加一步。

solution 函数:

  • 初始化:

total_steps 初始化为 0,用于累加所有数字变为 0 所需的总步数。

  • 遍历数组:

遍历输入数组 a 中的每个数字 num

  • 累加步数:

对于每个 num,调用 deleteSteps 函数计算将其变为 0 所需的最少步数,并累加到 total_steps

  • 返回结果:

最后,返回 total_steps,即数组中所有数字变为 0 所需的总步数。

5.代码实现
def deleteSteps(num):
    # 将数字转换为字符串,方便操作每一位数字
    num_str = str(num)
    if num == 0:
        return 0
    if len(num_str) == 1:
        return 1
    # 删除每一位数字后,剩余数字变为0所需的最少步数
    res = float('inf')
    for i in range(len(num_str)):
        # 删除当前位数字后,剩余数字
        new_num = int(num_str[:i] + num_str[i+1:])
        # 计算删除当前位数字后,剩余数字变为0所需的最少步数
        res = min(res, deleteSteps(new_num) + 1)
    return res

def solution(n: int, a: list) -> int:
    total_steps = 0
    for num in a:
        total_steps += deleteSteps(num)
    return total_steps

if __name__ == '__main__':
    print(solution(5, [10, 13, 22, 100, 30]) == 7)
    print(solution(3, [5, 50, 505]) == 4)
    print(solution(4, [1000, 1, 10, 100]) == 4)