【数据结构与算法】力扣 415. 字符串相加

题目描述

415. 字符串相加

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

分析解答

这道题本质是实现「大整数加法」,也就是模拟我们手写的“竖式加法”,要求不能用内建的 BigInt 或强转数字。


✅ 解题思路(模拟加法,倒着算)

我们从两个字符串的尾部开始加,每次加一位,同时维护一个 进位 carry,然后构造结果字符串。


✅ TypeScript 实现

双指针。

function addStrings(num1: string, num2: string): string {let i = num1.length - 1;let j = num2.length - 1;let carry = 0;let res = '';while (i >= 0 || j >= 0 || carry > 0) {const n1 = i >= 0 ? parseInt(num1[i]) : 0;const n2 = j >= 0 ? parseInt(num2[j]) : 0;const sum = n1 + n2 + carry;res = (sum % 10) + res;carry = Math.floor(sum / 10);i--;j--;}return res;
}

🔍 示例解析

示例 1:num1 = "456", num2 = "77"

   4 5 6
+     7 7
---------5 3 3 ✅

过程:

  • 6 + 7 = 13 → 写 3,进位 1
  • 5 + 7 + 1 = 13 → 写 3,进位 1
  • 4 + 0 + 1 = 5 → 写 5,进位 0

结果:"533"


✅ 时间和空间复杂度

  • 时间复杂度O(max(m, n)),m 和 n 是两个字符串的长度
  • 空间复杂度O(max(m, n)),结果字符串长度

思路拓展

这道题最好的做法就是双指针,直接操作字符串,如果使用数组的话,很容易出现超时或者栈溢出的报错。

写法一 - 超时做法

🚨 unshift() 是在数组最前面插入一个元素,它的时间复杂度是:

O(n) —— 每次都需要移动数组中已有的所有元素!

function addStrings(num1: string, num2: string): string {const arr1 = num1.split('')const arr2 = num2.split('')const res: number[] = []let carry = 0while (arr1.length || arr2.length || carry) {let num1 = arr1.length ? Number(arr1.pop()) : 0let num2 = arr2.length ? Number(arr2.pop()) : 0let sum = num1 + num2 + carryif (sum >= 10) carry = 1let cur = sum % 10res.unshift(cur)}return String(res.join())
};

写法二 - ?? 的错误使用

function addStrings(num1: string, num2: string): string {const arr1 = num1.split('')const arr2 = num2.split('')const res: number[] = []let carry = 0while (arr1.length || arr2.length || carry) {let num1 = Number(arr1.pop()) ?? 0let num2 = Number(arr2.pop()) ?? 0let sum = num1 + num2 + carryif (sum >= 10) carry = 1let cur = sum % 10res.push(cur)}return res.reverse().join('')
};

arr1.pop() 返回的是 string | undefined

如果是 undefined,传给 Number(…) 就变成 NaN

所以 Number(undefined) ?? 0 实际上返回的是 NaN,不会走到 ?? 0,因为 NaN ≠ null 或 undefined

正确的写法可以改为:

const n1 = arr1.length ? Number(arr1.pop()) : 0;
const n2 = arr2.length ? Number(arr2.pop()) : 0;// 或者是
const n1 = Number(arr1.pop() ?? '0');
const n2 = Number(arr2.pop() ?? '0');

写法三 - 栈溢出

function addStrings(num1: string, num2: string): string {const arr1 = num1.split('')const arr2 = num2.split('')const res: number[] = []let carry = 0while (arr1.length || arr2.length || carry) {let num1 = arr1.length ? Number(arr1.pop()) : 0let num2 = arr2.length ? Number(arr2.pop()) : 0let sum = num1 + num2 + carryif (sum >= 10) carry = 1let cur = sum % 10res.push(cur)}return res.reverse().join('')
}; 

报错:<— Last few GCs —>
[20:0xcfe3000] 1289 ms: Mark-Compact (reduce) 386.9 (396.3) -> 386.8 (389.3) MB, pooled: 0 MB, 46.23 / 0.00 ms (average mu = 0.639, current mu = 0.003) last resort; GC in old space requested
[20:0xcfe3000] 1340 ms: Mark-Compact (reduce) 386.8 (389.3) -> 386.8 (389.1) MB, pooled: 0 MB, 50.45 / 0.00 ms (average mu = 0.501, current mu = 0.000) last resort; GC in old space requested
<— JS stacktrace —>
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xe36196 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [nodejs run]

主要报错就是:JavaScript heap out of memory 内存溢出

这并不是代码逻辑有错,而是程序运行时占用了太多内存,触发了 V8 的内存限制(默认约为 512MB - 1.5GB)。因为是大数相加,所以同时频繁的:

pop()

Number(…)

res.push(…)

res.reverse()

join(‘’)

都会在大输入下产生巨大的临时对象 → 导致 GC频繁触发,最终内存耗尽。

虽然以下做法可以正常通过,但是并不推荐:

function addStrings(num1: string, num2: string): string {const arr1 = num1.split('');const arr2 = num2.split('');const res: number[] = [];let carry = 0;while (arr1.length || arr2.length || carry) {const n1 = arr1.length ? Number(arr1.pop()) : 0;const n2 = arr2.length ? Number(arr2.pop()) : 0;const sum = n1 + n2 + carry;res.push(sum % 10);carry = Math.floor(sum / 10);}return res.reverse().join('');
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91118.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进阶向:Manus AI与多语言手写识别

Manus AI与多语言手写识别:从零开始理解 手写识别技术作为人工智能领域的重要应用之一,近年来在智能设备、教育、金融等行业得到了广泛运用。根据市场调研机构IDC的数据显示,2022年全球手写识别市场规模已达到45亿美元,预计到2025年将突破70亿美元。其中,多语言手写识别技…

Javaweb————HTTP请求头属性讲解

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️前面我们已经说过http请求分为三部分&#xff0c;请求行&#xff0c;请求头和请求体 请求头包含若干个属性&#xff1a;格式为属性名&#xff1a;属性值&#xff0c;这篇文章我们就来介绍一下http请求头中一些常见属性的含义 我们…

9.c语言常用算法

查找顺序查找&#xff08;线性查找&#xff09;算法思想&#xff1a;从数组的第一个元素开始&#xff0c;逐个与目标值进行比较&#xff0c;直到找到目标值或查找完整个数组。时间复杂度&#xff1a;最好情况&#xff1a;O(1)&#xff08;目标在第一个位置&#xff09;最坏情况…

AI小智源码分析——音频部分(一)

一、源码跳转这里采用了函数重载来进行代码复用&#xff0c;当需要对I2S接口的数据进行配置&#xff0c;比如左右音道切换&#xff0c;可以使用第二个构造函数&#xff0c;这里小智使用的是第一个构造函数&#xff0c;即只传递I2S相关的引脚参数&#xff08;不带slot mask&…

【GNSS原理】【LAMBDA】Chapter.12 GNSS定位算法——模糊度固定LAMBDA算法[2025年7月]

Chapter.12 GNSS定位算法——模糊度固定LAMBDA算法 作者&#xff1a;齐花Guyc(CAUC) 文章目录Chapter.12 GNSS定位算法——模糊度固定LAMBDA算法一.整周模糊度理论1.LAMBDA算法干了一件什么事情&#xff1f;2.LAMBDA算法步骤&#xff08;1&#xff09;去相关&#xff08;Z变换…

计算机毕业设计java在线二手系统的设计与实现 基于Java的在线二手交易平台开发 Java技术驱动的二手物品管理系统

计算机毕业设计java在线二手系统的设计与实现z2n189&#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着互联网技术的飞速发展&#xff0c;二手交易市场也逐渐从传统的线下模式转…

如何进行项目复盘?核心要点分析

进行项目复盘需要明确复盘目标、确定复盘参与人员、选择合适的复盘方法、梳理项目过程与关键节点、分析成功与失败的原因、总结经验教训并制定改进计划。其中&#xff0c;选择合适的复盘方法尤其关键&#xff0c;常见的复盘方法包括鱼骨图分析法、SWOT分析法、PDCA循环法&#…

LeetCode 923.多重三数之和

给定一个整数数组 arr &#xff0c;以及一个整数 target 作为目标值&#xff0c;返回满足 i < j < k 且 arr[i] arr[j] arr[k] target 的元组 i, j, k 的数量。 由于结果会非常大&#xff0c;请返回 109 7 的模。 示例 1&#xff1a; 输入&#xff1a;arr [1,1,2,2,…

.Net日志系统Logging-五

日志概念 日志级别 NET (Microsoft.Extensions.Logging) 中定义的 6 个标准日志级别&#xff0c;按严重性从低到高排列&#xff1a; 日志级别数值描述典型使用场景Trace0最详细的信息&#xff0c;包含敏感数据&#xff08;如请求体、密码哈希等&#xff09;。仅在开发或深度故…

中国贸促会融媒体中心出海活动负责人、出海星球创始人莅临绿算技术

近日&#xff0c;中国贸促会融媒体中心出海活动负责人、出海星球创始人王思诺一行莅临广东省绿算技术有限公司&#xff0c;深入考察其核心技术产品与全球化布局。双方围绕绿算技术全栈产品体系、创新出海模式及生态共建展开深度对话。绿算技术作为国内智算基础设施领域的领军企…

【算法专题训练】06、数组双指针

1、数组 数组是由相同类型的元素组成的数据集合&#xff0c;并且占据一块连续的内存&#xff0c;按照顺序存储数据。 1.1、数组的特性&#xff1a; 数组元素通过下标获取数据数组对象初始化时&#xff0c;需要先指定数组容量大小&#xff0c;并根据容量大小分配内存。缺点&…

操作系统-lecture2(操作系统结构)

回顾下lecture1 swap区域不可以马上执行&#xff0c;即虚拟内存的数据和指令不可以被执行&#xff0c;得交换回到内存区域 操作系统的服务 主要提供两种服务 面向普通用户&#xff1a;user interface面向程序员&#xff1a;应用级程序代码 为用户 为用户提供了操作包括但不…

内网服务器实现从公网穿透

从6月份tplink的ddns失效之后&#xff0c;对于部分在内网运行的服务器&#xff0c;从公网访问就收到了部分影响。有好几个朋友找来&#xff0c;寻求帮助&#xff0c;看看怎么恢复原来的机制&#xff0c;可以从公网互联网访问内网服务器。方案一&#xff1a;如果有动态公网的客户…

vcs-编译+仿真+dump波形【IMP】

VCS仿真分为两步式(编译/compilation仿真/simulation)和三步式(分析/analysis细化/elaborationsimulation/仿真);注2:analysis/分析是三步式flow中仿真design的第一步&#xff0c;在此阶段将使用vhdlan或vlogan分析VHDL、Verilog、SystemVerilog和OpenVera文件。下面的部分包括…

程序代码篇---python向http界面发送数据

在 Python 中向 HTTP 界面发送数据&#xff0c;本质上是模拟用户在网页上填写表单、点击提交按钮的过程。这在自动化测试、数据上报、接口调用等场景中非常常用。下面用通俗易懂的方式介绍具体方法、实例代码和解析。核心原理网页上的数据发送&#xff08;比如提交表单&#xf…

mybatis-plus由mysql改成达梦数据库

前置条件: 达梦数据库设置了大小写敏感,我比较菜,改不动!先这么凑合着用吧; 因为设置了大小写敏感,所以所有的sql语句都要加 引号; 这样是会报错的: SELECT remark,createDept,createBy,createTime,updateBy,updateTime FROM sys_oss_config这样才可以 SELECT "create_…

设计模式:外观模式 Facade

目录前言问题解决方案结构代码前言 外观是一种结构型设计模式&#xff0c;能为程序库、框架或其他复杂类提供一个简单的接口。 问题 假设你必须在代码中使用某个复杂的库或框架中的众多对象。正常情况下&#xff0c; 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确…

【数据结构初阶】--二叉树(四)

&#x1f525;个人主页&#xff1a;草莓熊Lotso &#x1f3ac;作者简介&#xff1a;C研发方向学习者 &#x1f4d6;个人专栏&#xff1a; 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》 ⭐️人生格言&#xff1a;生活是默默的坚持&#xff0c;毅力是永久的…

三、平面度检测-差值法

方法一: dev_get_window (WindowHandle) *读取3通道彩色融合图 read_image (Image, ./XYZ彩色融合图.tiff) *拆分3个通道 decompose3 (Image, x, y, z) *将3个通道图像转换为3D模型 xyz_to_object_model_3d (x,y, z, ObjectModel3D) *显示动态3D模型 threshold (z, Regions,…

什么是数据编排?数据编排的流程、优势、挑战及工具有哪些?

目录 一、数据编排的定义与概念 1.数据编排的基本含义 2.数据编排与相关概念的区别 3.数据编排的重要性 二、数据编排的流程 1.需求分析&#xff1a; 2.数据源识别与连接&#xff1a; 3.数据抽取&#xff1a; 4.数据转换&#xff1a; 5.数据加载&#xff1a; 6.监控…