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

92 阅读5分钟

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

大数和中的极值位距离 - MarsCode

这题题主使用的方法非常差……几乎是暴力解题的,没有很巧妙的思想,如果有其它更好的方法请多多评论!

问题描述

给定两个字符串 string1string2,它们分别是两个超大数的字符串表示形式。计算这两个数相加后的字符串结果中的最大数和最小数之间的位数差距。如果结果中所有数字都相同,则差距为 0。如果最大或最小数出现多次,应该选择最靠近的位置差。

测试样例

  1. 输入: string1 = "111", string2 = "222"输出: 0
  2. 输入: string1 = "111", string2 = "34"输出: 1
  3. 输入: string1 = "999", string2 = "1"输出: 0
  4. 输入: string1 = "525", string2 = "474"输出: 0

算法原理与思路

问题分析

  1. 大数相加:由于输入可能是超大数,我们使用按位相加的方式来处理大数相加,类似于手工计算每一位的加法,并处理进位。
  2. 查找极值:相加后的结果字符串中,找出最大值和最小值及其所有出现位置。
  3. 计算差距:计算最大值和最小值之间的最小位数差距。如果所有数字相同,差距为 0

解题步骤

  1. 大数相加:实现一个函数,按位从低到高进行相加,处理可能的进位。
  2. 寻找最大最小值:遍历结果字符串,记录最大值和最小值的位置。
  3. 计算最小位差:比较最大和最小数的位置,找到最小的位数差。如果差距不足 2,则返回 0。

代码实现

Go 语言实现

package main

import (
	"fmt"
	"strings"
)

func solution(string1, string2 string) int {
	sumString := addLargeNumbers(string1, string2)

	// 找到最大和最小值
	minNum, maxNum := 10, -1
	minIndices, maxIndices := []int{}, []int{}

	// 遍历sumString来找出最大值和最小值的位置
	for i, char := range sumString {
		num := int(char - '0')

		// 更新最小值
		if num < minNum {
			minNum = num
			minIndices = []int{i} // 重新开始记录最小值的位置
		} else if num == minNum {
			minIndices = append(minIndices, i)
		}

		// 更新最大值
		if num > maxNum {
			maxNum = num
			maxIndices = []int{i} // 重新开始记录最大值的位置
		} else if num == maxNum {
			maxIndices = append(maxIndices, i)
		}
	}

	// 计算最小的位数差距
	minDifference := len(sumString) // 初始化为最大可能的差距
	for _, minIndex := range minIndices {
		for _, maxIndex := range maxIndices {
			difference := abs(minIndex - maxIndex)
			if difference < minDifference {
				minDifference = difference
			}
		}
	}

	if minDifference<2{
		return 0
	}
	return minDifference-1
}

// 绝对值计算函数
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

// 大数相加函数
func addLargeNumbers(num1 string, num2 string) string {
	// 确保 num1 是较长的字符串
	if len(num1) < len(num2) {
		num1, num2 = num2, num1
	}

	// 用来存储结果的字符串
	result := strings.Builder{}
	carry := 0

	// 从后往前遍历两个字符串
	for i := 0; i < len(num1) || carry > 0; i++ {
		var digit1, digit2 int

		// 获取 num1 的当前位
		if i < len(num1) {
			digit1 = int(num1[len(num1)-1-i] - '0')
		}

		// 获取 num2 的当前位
		if i < len(num2) {
			digit2 = int(num2[len(num2)-1-i] - '0')
		}

		// 计算当前位的和加上进位
		sum := digit1 + digit2 + carry
		carry = sum / 10                     // 更新进位
		result.WriteByte(byte(sum%10 + '0')) // 将当前位的结果加入结果字符串
	}

	// 将结果反转并返回
	// 使用 strings.Builder 避免多次字符串拼接造成的性能问题
	reversedResult := []byte(result.String())
	for i, j := 0, len(reversedResult)-1; i < j; i, j = i+1, j-1 {
		reversedResult[i], reversedResult[j] = reversedResult[j], reversedResult[i]
	}

	return string(reversedResult)
}

func main() {
	// 你可以添加更多的测试用例
	fmt.Println(solution("111", "222") == 0)                   // 应返回 0
	fmt.Println(solution("111", "34") == 1)                    // 应返回 1
	fmt.Println(solution("5976762424003073", "6301027308640389") == 6) // 复杂测试
	fmt.Println(solution("11112", "00001") == 0)                // 应返回 0
}

Python 版本实现

def solution(string1, string2):
    sum_string = add_large_numbers(string1, string2)

    # 找到最大和最小值
    min_num, max_num = 10, -1
    min_indices, max_indices = [], []

    # 遍历sum_string来找出最大值和最小值的位置
    for i, char in enumerate(sum_string):
        num = int(char)

        # 更新最小值
        if num < min_num:
            min_num = num
            min_indices = [i]  # 重新开始记录最小值的位置
        elif num == min_num:
            min_indices.append(i)

        # 更新最大值
        if num > max_num:
            max_num = num
            max_indices = [i]  # 重新开始记录最大值的位置
        elif num == max_num:
            max_indices.append(i)

    # 计算最小的位数差距
    min_difference = len(sum_string)  # 初始化为最大可能的差距
    for min_index in min_indices:
        for max_index in max_indices:
            difference = abs(min_index - max_index)
            if difference < min_difference:
                min_difference = difference

    if min_difference < 2:
        return 0
    return min_difference - 1


def add_large_numbers(num1, num2):
    # 确保 num1 是较长的字符串
    if len(num1) < len(num2):
        num1, num2 = num2, num1

    result = []
    carry = 0

    # 从后往前遍历两个字符串
    for i in range(len(num1)):
        digit1 = int(num1[len(num1) - 1 - i]) if i < len(num1) else 0
        digit2 = int(num2[len(num2) - 1 - i]) if i < len(num2) else 0

        # 计算当前位的和加上进位
        total = digit1 + digit2 + carry
        carry = total // 10  # 更新进位
        result.append(str(total % 10))  # 将当前位的结果加入结果字符串

    # 如果还有进位,需要追加
    if carry > 0:
        result.append(str(carry))

    # 将结果反转并返回
    return ''.join(reversed(result))


# 绝对值计算函数
def abs(a):
    return a if a >= 0 else -a


# 测试用例
if __name__ == "__main__":
    print(solution("111", "222") == 0)                    # 应返回 0
    print(solution("111", "34") == 1)                     # 应返回 1
    print(solution("5976762424003073", "6301027308640389") == 6)  # 复杂测试
    print(solution("11112", "00001") == 0)                 # 应返回 0

复杂度分析

  • 时间复杂度: O(n),其中 n 是大数字符串的长度,因为我们需要遍历每个字符来计算结果和找到极值位置。
  • 空间复杂度: O(n),因为需要存储结果字符串。