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

112 阅读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

解题思路

暴力解法

解题思路

我们需要解决的问题是:在 sum_str 中,找到 最小数字和最大数字的最小距离

  1. 字符串求和:将两个输入字符串转为整数后相加,再转换为字符串 sum_str。
  2. 寻找极值:使用内置函数 min 和 max 找到 sum_str 中的最小数字 min_digit 和最大数字 max_digit。
  3. 判断特例:若 min_digit 和 max_digit 相等,则所有数字相同,输出结果 0。
  4. 记录极值索引:找到 sum_str 中 min_digit 和 max_digit 所在的位置索引。
  5. 计算最小距离
    • 遍历所有 min_digit 和 max_digit 的位置索引,计算两者之间的绝对距离。
    • 选择其中的最小值作为结果。
def solution(string1, string2):
    # 1. 求和并转为字符串
    sum_str = str(int(string1) + int(string2))

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

    # 3. 判断特例
    if min_digit == max_digit:
        return 0

    # 4. 获取极值的索引
    min_indices = [i for i, ch in enumerate(sum_str) if ch == min_digit]
    max_indices = [i for i, ch in enumerate(sum_str) if ch == max_digit]

    # 5. 计算最小距离
    result = min(abs(max_idx - min_idx) for min_idx in min_indices for max_idx in max_indices)

# 6. 返回最终结果
return result - 1

时间复杂度

  1. 字符串转换和相加:

    • int(string1) + int(string2) 的时间复杂度是 O(n),其中 n 是字符串的长度。

    • str(int(string1) + int(string2)) 的时间复杂度也是 O(n)。 查找最小和最大数字:

    • min(sum_str) 和 max(sum_str) 的时间复杂度是 O(n),因为它们需要遍历整个字符串。

  2. 查找最小和最大数字的索引:

    • min_indices = [i for i, ch in enumerate(sum_str) if ch == min_digit] 和 max_indices = [i for i, ch in enumerate(sum_str) if ch == max_digit] 的时间复杂度是 O(n),因为它们需要遍历整个字符串。
  3. 计算最小和最大数字索引之间的最小差值:

    • result = min(abs(max_idx - min_idx) for min_idx in min_indices for max_idx in max_indices) 的时间复杂度是 O(m * k),其中 m 和 k 分别是 min_indices 和 max_indices 的长度。在最坏情况下,m 和 k 都可以达到 n,因此这一步的时间复杂度是 O(n^2)。

总体来说这样算法的时间复杂度为O(n2)O(n^2)

优化后的算法

我们可以在遍历字符串的时候,同时记录最小和最大数字的位置,实时计算他们之间的最小差值

  • 在遍历字符串时,记录最小和最大数字的位置。
  • 每次遇到新的最小或最大数字时,计算当前位置与之前记录的最小或最大数字位置之间的差值,并更新最小差值。

代码实现

def solution(string1, string2):
    sum_str = str(int(string1) + int(string2))
    min_digit = min(sum_str)
    max_digit = max(sum_str)

    if min_digit == max_digit:
        return 0

    min_diff = float('inf')
    last_min_index = -1
    last_max_index = -1

    for i, ch in enumerate(sum_str):
        if ch == min_digit:
            if last_max_index != -1:
                min_diff = min(min_diff, i - last_max_index)
            last_min_index = i
        elif ch == max_digit:
            if last_min_index != -1:
                min_diff = min(min_diff, i - last_min_index)
            last_max_index = i

    return min_diff - 1

这样的算法通过一次遍历就可以同时跟踪 min_digit 和 max_digit 的最近位置,从而在遇到新的匹配时计算出位差。可以将时间复杂度降低到O(n)O(n)