问题描述
小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
题目解析
本题的核心任务是对两个由数字字符组成的超大字符串数进行相加操作,然后在得到的结果字符串中确定最大数和最小数之间的位数差距。这涉及到两个关键步骤:一是实现高精度的大数加法,因为常规的数值数据类型无法直接处理超大数;二是在相加结果中精准地找出最大数和最小数,并计算它们的最小位置差。4
代码展示
def add_large_numbers(num1: str, num2: str) -> str:
"""实现大数加法"""
# 将较短的数字在前面补0,使两个数字长度相同
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 - 1 if min_distance != len(sum_str) else min_distance
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) # 结果是"333",所有数字相同,差距为0
print(solution("111", "34") == 1) # 结果是"145",最大值5和最小值1的位置差为1
print(solution("999", "1") == 0) # 结果是"1000",最大值1和最小值0的位置差为0
print(solution("525", "474") == 0) # 结果是"999",所有数字相同,差距为0
print(solution("5976762424003073", "6301027308640389") == 6) # 大数测试
思路分析
1. 大数加法实现( add_large_numbers 函数):
- 首先将两个输入字符串补零,使它们长度相同,便于后续按位相加操作。
- 从右向左逐位相加,同时考虑进位情况。将每一位的和对 10 取余作为结果字符串该位的值,和除以 10 的商作为进位。
- 处理完所有位后,如果最后还有进位,则添加到结果字符串的最左边。 2. 最小位置差计算( find_min_distance 函数):
- 若结果字符串所有数字相同,直接返回 0。
- 找到结果字符串中的最大数字和最小数字。
- 遍历字符串,记录最大数字和最小数字最后出现的位置。每当遇到最大或最小数字时,检查另一个极值是否已经出现过,如果出现过,则计算它们之间的位置差,并更新最小位置差。
知识总结
1. 字符串处理技巧:熟练掌握字符串的长度获取、补零操作、字符转换为数字以及字符串的拼接与反转等操作,这些是处理字符串表示的数字的基础。 2. 大数运算原理:理解大数加法的原理,即模拟手工计算加法的过程,逐位相加并处理进位,可推广到其他大数运算如减法、乘法等。 3. 极值位置计算方法:学会在遍历过程中记录特定值的位置,并通过比较位置来计算距离或差距,这种方法在很多数据处理和算法问题中有应用。
学习心得
通过解决本题,深刻体会到处理复杂问题时分解步骤的重要性。将大数相加和位置差计算分别封装成函数,使代码结构更清晰,易于理解和维护。在大数加法中,补零操作和从右向左计算的思路是解决问题的关键,这让我认识到对于特殊情况的预处理往往能简化后续的计算过程。在计算位置差时,通过巧妙地记录极值位置并及时更新最小距离,避免了大量不必要的计算。这启示我在算法设计中要多思考如何优化计算过程,减少不必要的计算资源浪费。同时,编写测试用例的过程也让我更加注重代码的准确性和鲁棒性,不仅要考虑正常情况,还要对边界情况和特殊情况进行充分测试,以确保代码在各种情况下都能正确运行。