leetcode
leetcode 351 ~ 400
字符串相加

字符串相加

难度:

标签:

题目描述

给定两个字符串形式的非负整数 num1num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

 

示例 1:

输入:num1 = "11", num2 = "123"
输出:"134"

示例 2:

输入:num1 = "456", num2 = "77"
输出:"533"

示例 3:

输入:num1 = "0", num2 = "0"
输出:"0"

 

 

提示:

  • 1 <= num1.length, num2.length <= 104
  • num1num2 都只包含数字 0-9
  • num1num2 都不包含任何前导零

代码结果

运行时间: 24 ms, 内存: 0.0 MB


/* 
 * This solution utilizes Java Stream to sum digits of two numbers represented as strings. 
 * It uses the IntStream to iterate and sum corresponding digits while keeping track of the carry.
 */
import java.util.stream.IntStream;
 
public class SolutionStream {
    public String addStrings(String num1, String num2) {
        int maxLength = Math.max(num1.length(), num2.length());
        int[] result = new int[maxLength + 1];
 
        IntStream.range(0, maxLength).forEach(i -> {
            int x = (i < num1.length()) ? num1.charAt(num1.length() - 1 - i) - '0' : 0;
            int y = (i < num2.length()) ? num2.charAt(num2.length() - 1 - i) - '0' : 0;
            int sum = x + y + result[i];
            result[i] = sum % 10;
            result[i + 1] = sum / 10;
        });
 
        StringBuilder sb = new StringBuilder();
        for (int i = result.length - 1; i >= 0; i--) {
            if (!(sb.length() == 0 && result[i] == 0)) {
                sb.append(result[i]);
            }
        }
        return sb.length() == 0 ? "0" : sb.toString();
    }
}

解释

方法:

该题解通过模拟手工加法的过程来计算两个字符串形式的数字的和。首先,从两个字符串的末尾开始逐位相加,并处理进位。具体步骤包括:初始化两个指针分别指向两个字符串的末尾,并用一个变量来存储进位。然后,逐位计算相应位置的数字之和,加上前一位的进位。将每位的结果存储在一个列表中,最后将列表逆序并转换为字符串形式返回。如果最终的进位不为零,还需要将其加到结果的最前面。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在处理字符串数字相加时,你是如何确保在进位处理过程中不会出现数值溢出的问题?
在字符串数字相加的实现中,由于每一位只处理单个字符转换后的数字,这些数字的范围是0到9。相加时最大可能的和为18(例如9 + 9),再加上可能的进位1,总和为19。处理这种情况时,我们通过模10的操作取得个位数,并通过整除10的操作得到新的进位(0或1),这样保证了每一步的计算不会超出处理单个字符的范围。因此,这种方法不会引起任何数值溢出问题,并能有效地处理任意长度的字符串数字加法。
🦆
为什么在最后要检查并移除结果列表中的多余0?在什么情况下会出现这些多余的0?
在字符串数字相加的实现中,最后检查并移除多余的0是为了处理输入字符串中可能存在的前导零,尤其是当输入字符串本身就是'0'或者有多个前导零时。这些前导零在数字反转并添加到结果列表后会变成尾部的0。例如,如果两个输入数字都是'0',结果列表可能会先添加一个'0',然后没有其他非零值添加进来,最终结果应该是一个单独的'0'而不是多个连续的'0'。
🦆
在将结果列表逆序并转换为字符串的过程中,有没有考虑过直接在列表中从头部插入元素以避免最后的逆序操作?这样做的复杂度和现有方法相比如何?
在实现中,可以考虑直接在结果列表的头部插入元素,以避免最后的逆序操作。这通常是通过在列表的开始使用insert(0, element)来实现。然而,这种方法的时间复杂度较高,因为每次插入都可能涉及整个列表的内存移动,其复杂度为O(n),而对于每一位数字都执行此操作,整体复杂度是O(n^2)。相比之下,先在列表末尾添加元素,然后最后进行一次逆序操作的方法,虽然也有额外的时间开销,但整体上只需要O(n)的时间复杂度,因此更高效。

相关问题

两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

 

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

 

提示:

  • 每个链表中的节点数在范围 [1, 100]
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

 

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

 

提示:

  • 1 <= num1.length, num2.length <= 200
  • num1 和 num2 只能由数字组成。
  • num1 和 num2 都不包含任何前导零,除了数字0本身。

数组形式的整数加法

整数的 数组形式  num 是按照从左到右的顺序表示其数字的数组。

  • 例如,对于 num = 1321 ,数组形式是 [1,3,2,1]

给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 num + k数组形式

 

示例 1:

输入:num = [1,2,0,0], k = 34
输出:[1,2,3,4]
解释:1200 + 34 = 1234

示例 2:

输入:num = [2,7,4], k = 181
输出:[4,5,5]
解释:274 + 181 = 455

示例 3:

输入:num = [2,1,5], k = 806
输出:[1,0,2,1]
解释:215 + 806 = 1021

 

提示:

  • 1 <= num.length <= 104
  • 0 <= num[i] <= 9
  • num 不包含任何前导零,除了零本身
  • 1 <= k <= 104