大数和中的极值位距离 | 豆包MarsCode AI 刷题

149 阅读4分钟

在学习编程和算法的过程中,处理字符串和数字的相关问题是一个重要的部分。特别是在面对超大数字字符串相加的问题时,如何有效地计算出结果中最大数与最小数之间的位数差距,成为了一个值得深入探讨的课题。本文将围绕这一问题进行详细解析,分享我的思路、代码实现以及一些学习心得。

1. 问题描述

小R面临一个挑战,她需要计算两个由数字字符组成的超大字符串数相加后的结果,并找出结果中最大数和最小数之间的位数差距。具体要求如下:

  • 如果结果中所有数字都相同,则位数差为0。
  • 如果存在多个符合最大或最小条件的数,应该选择最小的位置差。

示例分析

  • 示例1: 输入 string1 = "111"string2 = "222",结果为 "333",所有数字相同,因此位数差为0。
  • 示例2: 输入 string1 = "111"string2 = "34",结果为 "145",其中最大数是 '5' 位于第3位,最小数是 '1' 位于第1位,位差为1。
  • 示例3: 输入 string1 = "999"string2 = "1",结果为 "1000",所有数字相同,位数差为0。
  • 示例4: 输入 string1 = "525"string2 = "474",结果为 "999",所有数字相同,位数差为0。

2. 解题思路

为了求解这个问题,我们可以分为两个主要步骤:

  1. 实现大数加法:由于输入的数字可能非常大,直接使用整数类型进行计算可能不适用,因此我们需要实现一个函数来处理字符串形式的大数相加。
  2. 查找最大最小数字的位数差:在得到相加结果后,我们需要遍历结果字符串,找到最大数和最小数,并计算它们之间的位数差。

3. 代码实现

以下是实现上述思路的Python代码:

def add_large_numbers(num1: str, num2: str) -> str:
    """实现大数加法"""
    max_len = max(len(num1), len(num2))
    num1 = num1.zfill(max_len)
    num2 = num2.zfill(max_len)

    carry = 0  # 进位
    result = []

    # 从右向左逐位相加
    for i in range(max_len - 1, -1, -1):
        digit_sum = int(num1[i]) + int(num2[i]) + carry
        carry = digit_sum // 10
        result.append(str(digit_sum % 10))

    # 处理最后的进位
    if carry:
        result.append(str(carry))

    # 反转结果并转换为字符串
    return ''.join(result[::-1])

def find_min_distance(sum_str: str) -> int:
    """在结果字符串中找出最大值和最小值的最小位置差"""
    if len(set(sum_str)) == 1:  # 如果所有数字都相同
        return 0

    # 找到最大和最小数字
    max_digit = max(sum_str)
    min_digit = min(sum_str)

    # 记录每个数字最后出现的位置
    last_pos = {}
    # 记录当前找到的最小距离
    min_distance = len(sum_str)

    # 遍历字符串,记录位置并更新最小距离
    for i, digit in enumerate(sum_str):
        if digit == max_digit or digit == min_digit:
            # 如果另一个极值已经出现过
            for prev_digit, prev_pos in last_pos.items():
                if (digit == max_digit and prev_digit == min_digit) or \
                   (digit == min_digit and prev_digit == max_digit):
                    min_distance = min(min_distance, i - prev_pos)
            last_pos[digit] = i

    return min_distance if min_distance != len(sum_str) else -1

def solution(string1: str, string2: str) -> int:
    """主函数:计算两个大数相加后的最大最小值位置差"""
    # 计算两数之和
    sum_result = add_large_numbers(string1, string2)
    # 计算最大最小值的最小位置差
    return find_min_distance(sum_result)

if __name__ == "__main__":
    # 测试样例
    print(solution("111", "222") == 0)
    print(solution("111", "34") == 1)
    print(solution("999", "1") == 0)
    print(solution("525", "474") == 0)

4. 个人思考与总结

在实现这个问题的过程中,我体会到以下几点:

  1. 时间复杂度:

    • 大数加法的时间复杂度为O(N),其中N为字符串的长度。
    • 查找最大最小数字的时间复杂度为O(M),其中M为结果字符串的长度。
    • 整体的时间复杂度为O(N + M),在实际应用中表现良好。
  2. 空间复杂度:

    • 由于我们使用了额外的存储空间来保存结果和位置,空间复杂度为O(N)。
  3. 学习收获:

    • 通过这个问题,我更加深入地理解了字符串处理和动态规划的结合。尤其是在处理大数时,如何有效地进行字符串运算是一个值得研究的方向。
    • 在使用豆包MarsCode AI刷题的过程中,能够快速找到解决思路和优化代码的机会,帮助我在编程的道路上不断进步。

希望通过这篇文章的分享,能够帮助到正在使用豆包MarsCode AI刷题的同学们,让我们一起在编程的世界中不断探索与成长!