题目解析:小C的整数操作挑战 | 豆包MarsCode AI刷题

7 阅读5分钟

小C的整数操作挑战

一、问题分析

小C手中有一个正整数 n,她每次可以删除该数字中的一位数字。目标是最少操作次数,使它成为 5 的倍数。要分析是否为 5 的倍数,只需检查数字是否背基 5。即:数字的最后一位是 0 或 5。这是因为一个整数只有在最后一位为 0 或 5 时,才能整除 5。在实际问题中,删除操作会影响数字的结构,因此需要找到一种策略,既能够有效移除无用的数字,又能尽量保留有助于构造目标数字的部分。例如,对于一个多位数,如果删除操作能让剩余的数字中包含 05,并且位于末尾,则可以大大减少操作次数。

此外,还需注意以下特殊情况:

  1. 如果原数字本身已经是 5 的倍数,则不需要任何删除操作。
  2. 如果数字中不包含 05,那么需要删除所有数字才能达到目的。
  3. 在数字较长时,优先考虑最短路径,即尽量少操作即可获得结果。

因此,本题的关键在于如何高效地枚举可能的数字组合,并快速判断其是否满足 5 的倍数特性。

二、思路解析

  1. 枚举所有可能的删除操作:

    • 首先将数字 n 转化为字符串形式,便于操作。
    • 对于每种操作次数 ops,尝试删除 ops 个数字,保留剩余的数字。
    • 利用组合生成器(itertools.combinations)生成所有可能的数字组合。
  2. 检测倍数:

    • 对每一种数字组合,判断其是否是 5 的倍数。
    • 判断方法为:将组合后的数字重新拼接为字符串,转化为整数,检查其能否被 5 整除。
    • 一旦找到满足条件的组合,立即返回当前操作次数 ops,因为这已经是最优解。
  3. 统计操作次数:

    • 如果在所有组合中没有找到满足条件的数字,则需要删除所有数字,此时操作次数等于数字的长度。
    • 这种情况表明,输入数字中没有任何一个数字组合能够成为 5 的倍数。
  4. 优化策略:

    • 优先考虑长度较短且可能性较高的组合,例如数字中本身包含 05 时,优先保留这些数字。
    • 对于较大的数字,逐步减少搜索空间,避免不必要的组合计算。

三、代码详解

def solution(n: int) -> int:
    n_str = str(n)  # 将整数转化为字符串,便于操作每一位数字。
    length = len(n_str)  # 计算数字的长度,用于确定最大可能的操作次数。

    def is_divisible_by_5(number):
        """
        判断一个数字是否是 5 的倍数。
        输入:
        - number: 字符串形式的数字。
        输出:
        - bool: 是否是 5 的倍数。
        """
        return int(number) % 5 == 0

    # 主逻辑:从 0 次操作开始,逐步增加操作次数。
    for ops in range(length):
        from itertools import combinations  # 引入组合工具,生成删除后的所有可能组合。
        for combination in combinations(n_str, length - ops):
            # 将组合结果重新拼接为字符串
            number = ''.join(combination)
            # 如果拼接后的数字有效(非空)并且是 5 的倍数,则返回当前操作次数。
            if number and is_divisible_by_5(number):
                return ops

    # 如果所有组合均无法满足条件,则返回删除所有数字的操作次数。
    return length

# 测试用例
if __name__ == '__main__':
    print(solution(52) == 1)  # 题目例一:52 删除 2 后变成 5。
    print(solution(132) == 3)  # 题目例二:132 删除所有后满足条件。
    print(solution(1234) == 4)  # 题目例三:需要删除所有数字。

代码的核心思想是逐步减少数字的长度以检测其是否为 5 的倍数。首先,将整数转化为字符串形式,以便对每一位数字进行删除和组合操作。在主逻辑中,按操作次数递增的方式枚举所有可能的数字组合,利用 itertools.combinations 生成长度为 length - ops 的所有组合,并通过自定义的 is_divisible_by_5 函数检查这些组合是否满足 5 的倍数条件。一旦找到符合条件的组合,立即返回操作次数,从而保证结果是最优解。如果没有找到符合条件的数字,则返回需要删除所有数字的操作次数。此外,代码还处理了特殊边界情况,如数字中不包含 05 的情形,确保实现的健壮性和正确性。整体设计兼顾了效率和可读性,能够精准解决问题并覆盖所有可能的输入情况。

四、总结

本问题的核心目标是通过最少的操作次数,将给定数字调整为 5 的倍数。由于 5 的倍数的特性只与尾数相关,即最后一位必须为 05,算法设计围绕这一规则展开。具体而言,采用枚举和验证的方法,逐步删除数字中的位数并生成所有可能的组合。通过对每种组合的有效性进行检测(是否能被 5 整除),逐步优化操作次数,直至找到最优解。算法不仅通过从小到大的操作次数顺序搜索,确保了效率,还通过边界情况的详细处理(如数字完全不含 05),提高了对多种输入的适应性。

在实现过程中,代码充分体现了模块化设计的优势,例如通过分离组合生成和可整除验证的逻辑,提升了程序的可维护性和清晰度。此外,对于大规模数字,算法可以通过引入剪枝策略进一步优化,避免不必要的组合搜索。整体而言,该算法不仅能够高效地解决问题,还能扩展应用于其他整除问题,例如调整为 3、7 或其他数字的倍数,为类似问题提供了一种普适的解题思路。