leetcode
leetcode 901 ~ 950
数组形式的整数加法

数组形式的整数加法

难度:

标签:

题目描述

代码结果

运行时间: 60 ms, 内存: 16.7 MB


// Java Stream Solution
// 思路:和普通 Java 解决方案类似,但使用 Java Streams 将数组转换为字符串并处理后续操作。
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Solution {
    public List<Integer> addToArrayForm(int[] num, int k) {
        // 将数组转换为字符串
        String numberStr = Arrays.stream(num)
                                  .mapToObj(String::valueOf)
                                  .collect(Collectors.joining());
        // 将字符串转换为大整数并加上 k
        BigInteger number = new BigInteger(numberStr).add(BigInteger.valueOf(k));
        // 将结果转换为字符串
        String resultStr = number.toString();
        // 将字符串转换为数组形式
        return resultStr.chars()
                        .mapToObj(c -> c - '0')
                        .collect(Collectors.toList());
    }
}

解释

方法:

题解采用了模拟整数加法的方式来求解。首先,将整数k转换为数组形式num1,然后从右到左逐位相加,如果有进位,则记录进位值carry。循环继续,直到num和num1的所有位都处理完毕,且没有进位。最后将结果数组逆序,得到最终的数组形式的整数加法结果。

时间复杂度:

O(max(n, m))

空间复杂度:

O(m + n)

代码细节讲解

🦆
题解中提到,使用数组num1来存储整数k的数组形式。这种转换有没有可能出现问题,比如k非常大时的内存消耗?
将整数k转换为数组num1确实可能引起内存消耗问题,尤其是当k非常大时。例如,如果k是一个非常大的数,比如比int64还大的数,那么将这个数转换为数组后,数组的长度会很长,从而消耗大量内存。此外,Python虽然能够处理任意大小的整数,但大数的数组表示会导致更高的内存使用。在实际应用中,应当注意整数的范围和对应的内存管理策略。
🦆
解释中提到,最终结果数组ans是在循环结束后逆序得到的。为什么选择在最后进行逆序而不是在添加元素时直接按正确顺序插入?
在进行数组形式的整数加法时,从最低位(即数组的末尾)开始计算更直观,因为这模拟了我们通常的纸笔计算方法。如果从最高位开始计算,则需要频繁地在数组的前端插入元素,这在数组中是一个时间复杂度为O(n)的操作,因为每次插入都可能涉及到整个数组的移动。相反,向数组尾部添加元素是一个时间复杂度为O(1)的操作。因此,选择在最后进行一次逆序操作(时间复杂度为O(n))是一个更高效的策略。
🦆
在循环过程中,如果num和num1长度不一致,如何确保不会出现数组访问越界的错误?
在代码实现中,通过检查索引i和j是否大于或等于0来确保不会访问数组num和num1的越界元素。如果索引小于0,即对应的数组已经没有更多元素可以访问时,将对应的数值设为0(如x或y)。这样,即使num和num1的长度不一致,也能保证计算的进行而不会引发数组越界错误。
🦆
在处理进位时,题解使用了carry来累加并传递进位,这种处理方式在所有情况下都是有效的吗?可能存在哪些特殊情况需要额外注意?
使用carry变量来处理进位在大多数情况下是有效的,它确保了每位相加时超过基数(10)的部分能被正确地传递到下一位。需要特别注意的情况包括最后一次计算后仍存在进位的情况。例如,当最高位相加且仍有进位时,需要确保这个额外的进位能被加到结果数组的最前端。此外,当num或num1其中之一为负数时(虽然题目可能不涉及负数),carry处理逻辑可能需要调整,因为进位处理与负数的借位不完全相同。

相关问题

两数相加

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

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

你可以假设除了数字 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
  • 题目数据保证列表表示的数字不含前导零

加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

 

示例 1:

输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

示例 2:

输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。

示例 3:

输入:digits = [0]
输出:[1]

 

提示:

  • 1 <= digits.length <= 100
  • 0 <= digits[i] <= 9

二进制求和

给你两个二进制字符串 ab ,以二进制字符串的形式返回它们的和。

 

示例 1:

输入:a = "11", b = "1"
输出:"100"

示例 2:

输入:a = "1010", b = "1011"
输出:"10101"

 

提示:

  • 1 <= a.length, b.length <= 104
  • ab 仅由字符 '0''1' 组成
  • 字符串如果不是 "0" ,就不含前导零

字符串相加

给定两个字符串形式的非负整数 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 都不包含任何前导零