Skip to content

Commit 217127d

Browse files
committed
refactor: update tags documentation and add UMPIRE solution for Add-Two-Numbers problem
1 parent 3cb357d commit 217127d

3 files changed

Lines changed: 128 additions & 2 deletions

File tree

docs/Leetcode/0001.Two-Sum/README_solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Solution 1.Two-Sum
2+
title: UMPIRE 1.Two-Sum
33
subtitle: "https://leetcode.com/problems/two-sum/description/"
44
date: 2025-04-11T20:16:46+08:00
55
lastmod: 2025-04-11T20:16:46+08:00
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
---
2+
3+
# Solution - UMPIRE
4+
5+
## Output 1: UMPIRE 解題(完整思考版)
6+
7+
### U – Understand(理解題目)
8+
- **題目描述**:給予兩個非空的鏈結串列,分別代表兩個非負整數。數字是以「逆序」儲存的,意即鏈結串列的第一個節點代表個位數。請將這兩個數字相加,並以鏈結串列的形式回傳總和。
9+
- **關鍵限制**:
10+
- 每個節點只包含一個數字(0-9)。
11+
- 除非是數字 0 本身,否則這兩個數字都不會有前導零。
12+
- 兩個鏈結串列的長度可能不同。
13+
- **澄清與細節**:
14+
- 題目保證非空,所以不需處理空指標作為輸入的情況。
15+
- 需要處理進位(Carry)。
16+
- **測試案例定義**:
17+
- **Happy Path**:
18+
- $L1: [2, 4, 3]$ (342), $L2: [5, 6, 4]$ (465) $\rightarrow$ 結果: $[7, 0, 8]$ (807)
19+
- **Edge Cases**:
20+
- **長度不同**: $L1: [9, 9, 9, 9, 9, 9, 9]$, $L2: [9, 9, 9, 9] \rightarrow$ 需要處理不同步的結束。
21+
- **最後進位**: $L1: [5]$, $L2: [5] \rightarrow$ 結果: $[0, 1]$,最後多出一個節點。
22+
- **其中一個為零**: $L1: [0]$, $L2: [7, 3] \rightarrow$ 結果: $[7, 3]$。
23+
24+
### M – Match(匹配知識)
25+
- **主要演算法/資料結構**:鏈結串列遍歷(Linked List Traversal)與基礎算術(Elementary Math)。
26+
- **為什麼適合**:
27+
- 因為數字已經是逆序儲存,這非常符合我們手寫加法的習慣(從個位數開始加),我們只需要同時遍歷兩個串列即可。
28+
- **為什麼其他解法不理想**:
29+
- 若先將鏈結串列轉為大整數(BigInt)再相加後轉回串列,雖然可行,但會消耗額外的空間與轉換時間,且無法處理超過 64 位元整數範圍的情況(若題目沒有明確限制範圍)。直接在鏈結串列上操作是最直觀且有效率的。
30+
31+
### P – Plan(制定計畫)
32+
- **解題流程**:
33+
1. 初始化一個 `dummyHead` 節點來作為結果串列的起始,以及一個指標 `curr` 指向它。
34+
2. 初始化 `carry` 為 0。
35+
3. 同時遍歷 `l1` 和 `l2`,只要 `l1 != nil` 或 `l2 != nil` 或 `carry != 0` 就繼續迴圈:
36+
- 取得 `l1` 的值(若已結束則為 0)。
37+
- 取得 `l2` 的值(若已結束則為 0)。
38+
- 計算 `sum = val1 + val2 + carry`。
39+
- 更新 `carry = sum / 10`。
40+
- 創建新節點其值為 `sum % 10`,掛在 `curr.Next`。
41+
- 將 `curr`、`l1`、`l2` 分別移至下一個位置。
42+
4. 回傳 `dummyHead.Next`。
43+
- **資料流與狀態變化**:
44+
- 每次疊代都會處理一位數。
45+
- `carry` 狀態會在下一次疊代中被累加。
46+
- **預防 Bug**:
47+
- 注意迴圈結束條件,必須包含 `carry != 0`,否則最後一位進位會被遺漏(例如 5+5=10)。
48+
- 檢查指標是否為 `nil` 才能存取 `Val`。
49+
50+
### I – Implement(實際實作,Golang)
51+
```go
52+
/**
53+
* Definition for singly-linked list.
54+
* type ListNode struct {
55+
* Val int
56+
* Next *ListNode
57+
* }
58+
*/
59+
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
60+
dummyHead := &ListNode{Val: 0}
61+
curr := dummyHead
62+
carry := 0
63+
64+
for l1 != nil || l2 != nil || carry != 0 {
65+
val1, val2 := 0, 0
66+
if l1 != nil {
67+
val1 = l1.Val
68+
l1 = l1.Next
69+
}
70+
if l2 != nil {
71+
val2 = l2.Val
72+
l2 = l2.Next
73+
}
74+
75+
sum := val1 + val2 + carry
76+
carry = sum / 10
77+
curr.Next = &ListNode{Val: sum % 10}
78+
curr = curr.Next
79+
}
80+
81+
return dummyHead.Next
82+
}
83+
```
84+
85+
### R – Review(檢查與回顧)
86+
- **Dry Run**:
87+
- 輸入:$L1: [2, 4, 3], L2: [5, 6, 4]$
88+
- 1st: $2+5+0 = 7, carry=0, Result: [7]$
89+
- 2nd: $4+6+0 = 10, carry=1, Result: [7, 0]$
90+
- 3rd: $3+4+1 = 8, carry=0, Result: [7, 0, 8]$
91+
- 結束。回傳 $[7, 0, 8]$。
92+
- **關鍵狀態轉移**:`carry` 正確地從十位數轉移到下一位的個位數。
93+
- **邊界確認**:如果輸入是 $L1:[9], L2:[1]$,迴圈會跑兩次,第二次處理 `carry=1`,產出 $[0, 1]$,正確。
94+
95+
### E – Evaluate(總結與評估)
96+
- **時間複雜度**: $O(\max(M, N))$,其中 $M$ 和 $N$ 分別為兩個串列的長度。我們只需遍歷最長的那一個一次。
97+
- **空間複雜度**: $O(\max(M, N))$,回傳的結果串列長度最多為 $\max(M, N) + 1$。若不計入回傳空間,則為 $O(1)$。
98+
- **權衡與優化**:這個方法已經是時間與空間的最優解。唯一的優化可能是原位(In-place)修改,但因為相加後長度可能增加,且通常不建議修改輸入參數,所以使用新串列是標準做法。
99+
100+
---
101+
102+
## Output 2: 面試官口語回答腳本(精簡可直接說)
103+
104+
### 1️⃣ 開場:題目理解
105+
這題要求我們將兩個以逆序鏈結串列表示的整數相加,並回傳同樣是逆序的結果串列。核心在於如何處理兩串列長度不等的情況,以及數值相加後的進位處理。
106+
107+
### 2️⃣ 解法選擇說明
108+
我會採用**同時遍歷(Simultaneous Traversal)**的方法。因為題目給的數字已經是從個位數開始的逆序排列,這正好符合手算加法從右到左的邏輯。這種做法的時間複雜度是線性 $O(\max(M, N))$,是最直觀且高效的解法。
109+
110+
### 3️⃣ 解題策略概覽
111+
我會建立一個 Dummy Head 來簡化鏈結串列的操作。接著使用一個 `while` 迴圈同時遍歷兩個串列,並維護一個 `carry` 變數來存儲進位值。在每一次疊代中,我把兩個節點的值與當前的進位相加,取餘數作為新節點的值,取商數作為下一次的進位。這個迴圈會持續運行,直到兩個串列都走完「且」進位值為 0。
112+
113+
### 4️⃣ 寫程式時會補充的關鍵說明
114+
* **Dummy Head 的使用**:這可以讓我們在建立結果串列時,不需要特別判斷第一個節點是否為空,代碼會更簡潔。
115+
* **防呆判斷**:在取值時,一定要先檢查指標是否為 `nil`,如果其中一個串列比較短,我們就補 0 進行運算。
116+
* **最後進位處理**:迴圈的條件必須包含 `carry != 0`,確保像是 $99 + 1$ 這種最後產生的進位能被正確補在串列末端。
117+
118+
### 5️⃣ 快速 Dry Run 說明
119+
以 $[2, 4, 3]$ 加 $[5, 6, 4]$ 為例:
120+
第一位 $2+5=7$,無進位。
121+
第二位 $4+6=10$,寫 $0$ 進位 $1$。
122+
第三位 $3+4$ 再加上剛才的進位 $1$ 等於 $8$。
123+
最後結果就是 $[7, 0, 8]$。
124+
125+
### 6️⃣ 收尾總結
126+
這套演算法的**時間複雜度是 $O(\max(M, N))$****空間複雜度也是 $O(\max(M, N))$**(用於儲存結果)。這種解法穩定且能處理極大的數值,因為它完全避開了整數溢出的限制。

docs/tags.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# 標籤索引
1+
# tags
22

33
這是本專案所有題目的標籤分類。

0 commit comments

Comments
 (0)