每日一题——大数加法

题目描述

以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。

数据范围

  • 字符串长度 (1 \leq \text{len}(s), \text{len}(t) \leq 100000)
  • 字符串仅由 '0''9' 构成

要求

  • 时间复杂度 (O(n))

示例

示例 1

输入
s = "1", t = "99"
输出
"100"
说明
(1 + 99 = 100)

示例 2

输入
s = "114514", t = ""
输出
"114514"


解题思路

模拟手工加法

  1. 从低位到高位逐位相加

    • 从两个字符串的末尾开始,逐位相加,并处理进位。
    • 如果某一位的和大于等于 10,则产生进位。
  2. 处理不等长字符串

    • 如果两个字符串长度不同,较短的字符串在高位补 0。
  3. 处理最终进位

    • 如果最高位相加后仍有进位,需要在结果的最前面添加一个 1
  4. 结果反转

    • 由于是从低位到高位计算的,最终结果需要反转。

代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 逆转字符串
void reverseString(char* str, int length) {
    int start = 0;
    int end = length - 1;
    while (start < end) {
        // 交换首尾字符
        char temp = str[start];
        str[start] = str[end];
        str[end] = temp;
        // 移动指针
        start++;
        end--;
    }
}

// 计算两个大整数的和
char* solve(char* s, char* t) {
    // 获取两个字符串的长度
    int len1 = strlen(s);
    int len2 = strlen(t);

    // 如果其中一个字符串为空,直接返回另一个字符串
    if (len1 == 0) {
        char* result = (char*)malloc(sizeof(char) * (len2 + 1));
        strcpy(result, t);
        return result;
    }
    if (len2 == 0) {
        char* result = (char*)malloc(sizeof(char) * (len1 + 1));
        strcpy(result, s);
        return result;
    }

    // 结果的最大长度(取较长的长度 + 1,用于进位)
    int len = (len1 > len2 ? len1 : len2) + 1;
    // 初始化进位标志
    int jinwei = 0;
    int a = 0, b = 0;

    // 分配结果字符串的内存
    char* result = (char*)malloc(sizeof(char) * (len + 1)); // +1 用于存储 '\0'

    // 从字符串末尾开始逐位相加
    for (int i = 0; i < len - 1; i++) {
        // 获取 s 的当前位(如果还有剩余)
        if (len1 > 0) {
            a = s[--len1] - '0'; // 将字符转换为整数
        } else {
            a = 0;
        }

        // 获取 t 的当前位(如果还有剩余)
        if (len2 > 0) {
            b = t[--len2] - '0'; // 将字符转换为整数
        } else {
            b = 0;
        }

        // 计算当前位的和(包括进位)
        int sum = a + b + jinwei;
        // 如果和大于等于 10,设置进位标志
        if (sum >= 10) {
            jinwei = 1;
            sum -= 10; // 减去 10,取个位数
        } else {
            jinwei = 0; // 清除进位标志
        }

        // 将结果存储为字符
        result[i] = sum + '0'; // 将整数转换为字符
    }

    // 如果最后还有进位,在结果末尾添加 '1'
    if (jinwei) {
        result[len - 1] = '1';
        result[len] = '\0'; // 添加字符串结束符
        reverseString(result, len); // 逆转结果字符串
    } else {
        result[len - 1] = '\0'; // 添加字符串结束符
        reverseString(result, len - 1); // 逆转结果字符串
    }

    return result;
}

代码解析

1. reverseString 函数

  • 用于反转字符串。
  • 通过交换首尾字符实现。

2. solve 函数

  • 初始化
    • 获取两个字符串的长度。
    • 分配结果字符串的内存。
  • 逐位相加
    • 从字符串末尾开始,逐位相加,并处理进位。
    • 如果某一位的和大于等于 10,则产生进位。
  • 处理最终进位
    • 如果最高位相加后仍有进位,在结果的最前面添加一个 1
  • 结果反转
    • 由于是从低位到高位计算的,最终结果需要反转。
  • 返回结果
    • 返回计算结果的字符串。

复杂度分析

  • 时间复杂度:(O(n)),其中 (n) 是两个字符串中较长的长度。
  • 空间复杂度:(O(n)),用于存储结果字符串。

测试用例

测试用例 1

输入
s = "1", t = "99"
输出
"100"

测试用例 2

输入
s = "114514", t = ""
输出
"114514"

测试用例 3

输入
s = "123", t = "456"
输出
"579"

测试用例 4

输入
s = "999", t = "1"
输出
"1000"


总结

通过模拟手工加法的方式,我们可以高效地计算两个大整数的和。以下是代码的核心逻辑:

步骤说明
逐位相加从低位到高位逐位相加
处理进位如果和大于等于 10,产生进位
结果反转将结果反转以得到正确顺序
处理空字符串直接返回非空字符串的副本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tt555555555555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值