刷题记录5 | 豆包MarsCode AI刷题

47 阅读4分钟

问题描述

小R面对一个问题,她有两个由数字字符组成的超大字符串数,需要求出这两个数相加后得到的字符串数中的最大数和最小数之间的位数差距。如果结果中所有数字都相同,则差距为 0。如果存在多个符合最大或最小条件的数,应该选择最小的位置差。

例如,字符串数 "111" 和 "222" 相加得到 "333",所有数字相同,因此位数差为 0。另一例子,字符串数 "111" 和 "34" 相加得到 "145",其中最大数是 '5' 位于第 3 位,最小数是 '1' 位于第 1 位,他们之间的位差为 1。


测试样例

样例1:

输入:string1 = "111",string2 = "222"
输出:0

样例2:

输入:string1 = "111",string2 = "34"
输出:1

样例3:

输入:string1 = "999",string2 = "1"
输出:0

样例4:

输入:string1 = "525",string2 = "474"
输出:0

代码实现细节

  • 大数加法函数 add_strings

    • 字符串反转:  num1 = num1[::-1],方便从最低位开始相加。
    • 逐位相加:  使用循环迭代每一位,处理可能的进位。
    • 处理进位:  如果最高位有进位,需要在结果中追加。
    • 结果反转:  最后将结果列表反转,拼接成字符串返回。 解题:
def solution(string1: str, string2: str) -> int:
    # 大数加法,结果保存在字符串中
    def add_strings(num1: str, num2: str) -> str:
        # 反转字符串,便于从最低位开始相加
        num1 = num1[::-1]
        num2 = num2[::-1]
        result = []
        carry = 0
        max_length = max(len(num1), len(num2))
        for i in range(max_length):
            digit1 = int(num1[i]) if i < len(num1) else 0
            digit2 = int(num2[i]) if i < len(num2) else 0
            total = digit1 + digit2 + carry
            carry = total // 10
            result.append(str(total % 10))
        if carry:
            result.append(str(carry))
        # 结果需要再反转回来
        return ''.join(result[::-1])
    
    # 执行大数加法
    sum_str = add_strings(string1, string2)
    
    # 找到最大数和最小数,以及它们的所有位置
    max_digit = max(sum_str)
    min_digit = min(sum_str)
    
    # 如果所有数字都相同,位数差为0
    if max_digit == min_digit:
        return 0
    
    # 记录最大数和最小数的所有位置(下标从1开始)
    max_positions = [i+1 for i, ch in enumerate(sum_str) if ch == max_digit]
    min_positions = [i+1 for i, ch in enumerate(sum_str) if ch == min_digit]
    
    # 计算所有可能的位数差,找到最小的那个
    min_distance = float('inf')
    for pos_max in max_positions:
        for pos_min in min_positions:
            if pos_max != pos_min:
                distance = abs(pos_max - pos_min) - 1  # 位数差为两位置之差减一
                if distance < min_distance:
                    min_distance = distance
    # 如果最大数和最小数在相同位置,则差距为0
    if min_distance == float('inf'):
        return 0
    return min_distance

解析与思考

问题分析

题目要求:

  • 将两个超大的数字字符串相加,得到结果字符串。

  • 在结果字符串中,找到最大数字和最小数字之间的最小位数差。

    • 位数差定义为:两个数字的位置之差减一,即 abs(pos_max - pos_min) - 1
  • 如果结果中所有数字都相同,则位数差为 0。

  • 如果存在多个最大或最小数字,取位数差最小的那一对。

注意事项:

  • 由于数字字符串可能非常大,无法使用内置的整数类型进行运算,需要手动实现大数加法。
  • 需要准确地处理字符串的反转、下标和位置关系。

解题思路

  1. 实现大数加法:

    • 将字符串反转,从最低位开始逐位相加。
    • 注意处理进位。
    • 最终将结果反转,得到正确的和。
  2. 查找最大数和最小数以及它们的位置:

    • 使用内置的 max() 和 min() 函数找到结果字符串中的最大和最小数字字符。
    • 遍历结果字符串,记录最大数和最小数的所有出现位置(位置下标从 1 开始)。
  3. 计算最小位数差:

    • 对于每一个最大数的位置,遍历所有最小数的位置,计算位数差 abs(pos_max - pos_min) - 1
    • 记录所有可能的位数差,取其中的最小值。
  4. 特殊情况处理:

    • 如果最大数和最小数相同,说明结果字符串中所有数字都相同,位数差为 0。
    • 如果最大数和最小数在同一位置,位数差也为 0。