【數據結構與算法】力扣 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
英文地址,請注明出處:http://en.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.監控…