数组形式的整数加法

标签: 数组 数学

难度: Easy

整数的 数组形式  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

Submission

运行时间: 60 ms

内存: 16.7 MB

class Solution:
    def addToArrayForm(self, num: List[int], k: int) -> List[int]:
        num1 = list(map(int, str(k)))

        i, j = len(num) - 1, len(num1) - 1
        carry = 0
        ans = []

        while i >= 0 or j >= 0 or carry != 0:
            x = num[i] if i >= 0 else 0
            y = num1[j] if j >= 0 else 0
            result = x + y + carry
            ans.append(result % 10)
            carry = result // 10
            i -= 1
            j -= 1
        
        return ans[::-1]

Explain

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

时间复杂度: O(max(n, m))

空间复杂度: O(m + n)

class Solution:
    def addToArrayForm(self, num: List[int], k: int) -> List[int]:
        num1 = list(map(int, str(k)))  # 将整数k转换为数组

        i, j = len(num) - 1, len(num1) - 1
        carry = 0
        ans = []

        while i >= 0 or j >= 0 or carry != 0:
            x = num[i] if i >= 0 else 0  # 获取num的当前位,如果超出范围则为0
            y = num1[j] if j >= 0 else 0  # 获取num1的当前位,如果超出范围则为0
            result = x + y + carry  # 计算当前位的和,包括进位
            ans.append(result % 10)  # 将当前位的和的个位数添加到结果数组
            carry = result // 10  # 更新进位
            i -= 1
            j -= 1
        
        return ans[::-1]  # 将结果数组逆序,得到最终结果

Explore

将整数k转换为数组num1确实可能引起内存消耗问题,尤其是当k非常大时。例如,如果k是一个非常大的数,比如比int64还大的数,那么将这个数转换为数组后,数组的长度会很长,从而消耗大量内存。此外,Python虽然能够处理任意大小的整数,但大数的数组表示会导致更高的内存使用。在实际应用中,应当注意整数的范围和对应的内存管理策略。

在进行数组形式的整数加法时,从最低位(即数组的末尾)开始计算更直观,因为这模拟了我们通常的纸笔计算方法。如果从最高位开始计算,则需要频繁地在数组的前端插入元素,这在数组中是一个时间复杂度为O(n)的操作,因为每次插入都可能涉及到整个数组的移动。相反,向数组尾部添加元素是一个时间复杂度为O(1)的操作。因此,选择在最后进行一次逆序操作(时间复杂度为O(n))是一个更高效的策略。

在代码实现中,通过检查索引i和j是否大于或等于0来确保不会访问数组num和num1的越界元素。如果索引小于0,即对应的数组已经没有更多元素可以访问时,将对应的数值设为0(如x或y)。这样,即使num和num1的长度不一致,也能保证计算的进行而不会引发数组越界错误。

使用carry变量来处理进位在大多数情况下是有效的,它确保了每位相加时超过基数(10)的部分能被正确地传递到下一位。需要特别注意的情况包括最后一次计算后仍存在进位的情况。例如,当最高位相加且仍有进位时,需要确保这个额外的进位能被加到结果数组的最前端。此外,当num或num1其中之一为负数时(虽然题目可能不涉及负数),carry处理逻辑可能需要调整,因为进位处理与负数的借位不完全相同。