中不中等题 | 豆包MarsCode AI刷题

203 阅读3分钟

中等题:大数和中的极值位距离

题目链接:www.marscode.cn/practice/en…

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

样例1:

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

样例2:

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

样例3:

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

题意分析

给定两个数字字符串,计算他们的和sum,返回sum中最大数字与最小数字的位数差,若有相同的最大数字或最小数字,那么取最小的位数差。(注意:此处的位差是指两个位置之间的位数,即两个位置相减后还应再减1)。如样例3,和为1000,最大数字为1,在第0位,而第1、2、3位均为最小数字,那么取第1位0,与第0位距离最近,位差 = 1-0-1=0。

思路分析

将两个字符串转为int型相加,结果中的每个数字拆分放置一个列表中。要考虑以下几点。

  • 剪枝:所有数字相同,直接return 0 即可
  • 普通情况:最大和最小数字有且仅有一个。找出其中的最大值和最小值,直接计算返回两个位置之间的差。
  • 特殊情况:有多个相同的最大和最小数字。要找出所有最大、最小的位置,并且返回位差的最小值。
  • 特殊情况不失一般性,所以不用分类处理。

代码怎么写?

此题最重要的部分是如何找到最小位差?可以将所有相同的最大值位置索引放入一个列表,将所有相同的最小值位置索引放入另一个列表,两层遍历,找出最小位差即可。以下是比较清晰明了的代码(含注释)

def solution(string1, string2):
    s1 = int(string1)
    s2 = int(string2)
    su = list(map(int, str(s1 + s2)))
    # 剪枝:若和的所有数字相同(即最大值=最小值),返回0
    if max(su) == min(su):
        return 0
    maxi = max(su)
    mini = min(su)
    min_index, max_index = [], []
    # 找出所有最大值、最小值所在的索引位置,并分别添加至两个索引列表中
    for i in range(len(su)):
        if su[i] == maxi:
            max_index.append(i)
        if su[i] == mini:
            min_index.append(i)
    # 遍历两个索引列表,寻找最小位差
    mini = float('inf')
    for i in range(len(max_index)):
        for j in range(len(min_index)):
            mini = min(mini, abs(max_index[i] - min_index[j]))
    return mini - 1

总结与反思

考虑到特殊情况时,首先是想到用left, right双指针来写,分别从第0位和最后一位向中间收缩,直至找到最小位差。但是这种写法忽略了数字的顺序,并不是所有最小值都在所有最大值的左边,例如“13481617898”。

豆包MarsCode AI

另外,本题如果你让豆包MarsCode给你代码,它的思路只考虑了普通情况,你可以纠正他的思路并让他提供正确的代码,但它的最后返回值仍然缺少“-1”,需要你明确纠正它才会给出正确的代码。很多题目的题意并不清晰,需要我们自己解读,如果你没有正确理解题意并且拥有正确的解题思路,只是问MarsCode该怎么做,那么有些题目它给出的代码是无法运行通过的。