Skip to content

Commit 672c3c7

Browse files
committed
refactor: update README for Two-Sum and Add Two Numbers to improve clarity and consistency in problem descriptions, solution strategies, and formatting
1 parent c1c18f8 commit 672c3c7

2 files changed

Lines changed: 121 additions & 107 deletions

File tree

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,121 @@
11
---
2-
title: UMPIRE 0001.Two-Sum
2+
title: UMPIRE 0001.Two Sum
33
tags:
44
- Easy
55
author: Kimi Tsai <kimi0230@gmail.com>
6-
description: UMPIRE Solution for Two Sum problem
6+
description: UMPIRE Solution for 0001.Two Sum
77
math:
88
enable: true
99
---
1010

11-
# UMPIRE 0001.Two-Sum
11+
# UMPIRE 0001.Two Sum
1212

1313
## Output 1: UMPIRE 解題(完整思考版)
1414

1515
### U – Understand(理解題目)
16-
- **題目描述**給定一個整數陣列 `nums` 和一個目標值 `target`,請在該陣列中找出和為目標值的那兩個整數,並返回它們的陣列下標
16+
- **題目描述**在一個整數陣列 `nums` 中,找出兩個數字,其總和等於給定的目標值 `target`。返回這兩個數字的陣列索引
1717
- **關鍵限制**
18-
- 每種輸入只會對應一個答案。
19-
- 不能重複使用陣列中同樣的元素(即同一個 index 不能用兩次)。
20-
- 答案可以按任意順序返回。
21-
- **潛在陷阱**
22-
- 陣列中可能包含負數。
23-
- 陣列可能未排序(此題未註明排序,不能直接用雙指針而不先排序)。
18+
- 每種輸入正好只有一個解。
19+
- 同一個元素不能使用兩次(索引不能重複)。
20+
- 答案順序不限。
2421
- **Happy Path**
25-
- `nums = [2, 7, 11, 15], target = 9` -> 返回 `[0, 1]`
22+
- `nums = [2, 7, 11, 15], target = 9` -> 返回 `[0, 1]` ($2 + 7 = 9$)
2623
- **Edge Cases**
27-
- `nums = [3, 3], target = 6` -> 返回 `[0, 1]`(數值相同但 index 不同)
28-
- `nums = [3, 2, 4], target = 6` -> 返回 `[1, 2]`(目標值由非連續元素組成)
24+
- 補數在當前數字之後:`nums = [3, 2, 4], target = 6` -> 返回 `[1, 2]` ($2 + 4 = 6$)
25+
- 陣列包含負數:`nums = [-1, -2, -3, -4, -5], target = -8` -> 返回 `[2, 4]` ($-3 + -5 = -8$)
2926

3027
### M – Match(匹配知識)
31-
- **主要模式****Hash Map (Hash Table)**
28+
- **主要模式****Hash Map (雜湊表)**
3229
- **為什麼適合**
33-
- 我們需要快速尋找「當前數值的互補值」(即 `target - nums[i]`)是否已經在之前出現過。Hash Map 的查找時間複雜度為 $O(1)$,比起線性尋找的 $O(n)$ 快得多
30+
- 為了將搜尋時間從 $O(n)$ 降到 $O(1)$,我們可以使用 Hash Map 存儲已經遍歷過的數字及其對應的索引。這使得我們對於每個數字 `x`,都能在常數時間內判斷 `target - x` 是否已經出現過
3431
- **其他方案**
35-
- **暴力解 (Brute Force)**雙層迴圈遍歷所有組合。時間複雜度 $O(n^2)$,效率較低
36-
- **排序 + 雙指針**先排序再從兩端逼近。時間複雜度 $O(n \log n)$(受限於排序),雖然空間複雜度可降至 $O(1)$,但若題目要求返回原始下標,排序會打亂位置,需額外處理,不如 Hash Map 直觀且快
32+
- **暴力解 (Brute Force)**使用雙層迴圈檢查所有可能的配對。時間複雜度為 $O(n^2)$,在資料量大時效率極低
33+
- **排序 + 雙指針**先對陣列排序,然後使用左右指針逼近目標值。時間複雜度為 $O(n \log n)$。雖然空間複雜度優於 Hash Map,但排序會改變索引位置,需要額外處理
3734

3835
### P – Plan(制定計畫)
39-
1. 初始化一個空的分佈式雜湊表 (Map),用來儲存 `數值 : 下標` 的映射。
40-
2. 遍歷陣列 `nums`,對於每個元素 `v` 和其索引 `i`
41-
- 計算需要的互補值 `complement = target - v`
42-
- 在 Map 中檢查 `complement` 是否已存在:
43-
- 如果**存在**:表示找到答案,返回 `[Map[complement], i]`
44-
- 如果**不存在**:將當前數值與索引存入 Map `Map[v] = i`
45-
3. 如果遍歷結束仍未找到(根據題目假設這不會發生),返回空或預設值。
46-
- **避免的 Bug**:先檢查再存入,可以自然避免「重複使用同一個元素」的問題(因為 Map 裡只會有之前處理過的元素)。
36+
1. 建立一個空的 Map `m`,其中鍵 (key) 為數字的值,值 (value) 為數字在陣列中的索引。
37+
2. 遍歷陣列 `nums` 中的每一個元素 `v` 與其索引 `i`
38+
- 計算所需的補數 `complement = target - v`
39+
- 檢查 `complement` 是否已經存在於 `m` 中。
40+
- 如果**存在**:表示我們找到了那一對數字,返回 `[m[complement], i]`
41+
- 如果**不存在**:將當前數字 `v` 與索引 `i` 存入 `m` 中,以便後續元素查找。
42+
3. 如果遍歷完整個陣列仍未找到(根據題目假設這不會發生),則返回預設值。
43+
44+
**Mermaid Diagram**:
45+
```mermaid
46+
graph TD
47+
A[開始遍歷 nums] --> B{計算 complement = target - v}
48+
B --> C{"Map 中是否有 complement?"}
49+
C -- 有 --> D["返回 [Map[complement], 當前索引 i]"]
50+
C -- 無 --> E["將 {v: i} 存入 Map"]
51+
E --> F{是否還有元素?}
52+
F -- 是 --> A
53+
F -- 否 --> G[結束]
54+
```
4755

4856
### I – Implement(實際實作,Golang)
4957
```go
5058
func twoSum(nums []int, target int) []int {
51-
// 建立一個 map,key 是數值,value 是對應的索引
52-
m := make(map[int]int)
53-
54-
for i, v := range nums {
55-
complement := target - v
56-
// 檢查互補值是否已經在 map 中
57-
if idx, ok := m[complement]; ok {
58-
return []int{idx, i}
59-
}
60-
// 如果沒找到,把當前數值存入 map
61-
m[v] = i
62-
}
63-
64-
return []int{}
59+
// 初始化 map,用於存儲:數值 -> 索引
60+
m := make(map[int]int)
61+
62+
for i, v := range nums {
63+
complement := target - v
64+
// 檢查補數是否已在之前遍歷的元素中
65+
if idx, ok := m[complement]; ok {
66+
return []int{idx, i}
67+
}
68+
// 若沒找到,將當前元素存入 map
69+
m[v] = i
70+
}
71+
72+
return []int{}
6573
}
6674
```
6775

6876
### R – Review(檢查與回顧)
69-
- **Dry Run**:以 `nums = [3, 2, 4], target = 6` 為例:
70-
1. `i=0, v=3``complement=3`。Map 為空,不匹配。Map 存入 `{3: 0}`
71-
2. `i=1, v=2``complement=4`。Map 只有 `{3: 0}`,不匹配。Map 存入 `{3: 0, 2: 1}`
72-
3. `i=2, v=4``complement=2`。Map 存在鍵 `2`,其索引為 `1`。匹配成功。
73-
4. 返回 `[1, 2]`
74-
- **狀態轉換**:Map 會動態紀錄掃描過的數字,將原本需要二次掃描的查找降為 $O(1)$。
77+
- **Dry Run**`nums = [3, 2, 4], target = 6`
78+
1. `i = 0, v = 3``complement = 3`。Map 為空。存入 `{3: 0}`
79+
2. `i = 1, v = 2``complement = 4`。Map 只有 `{3: 0}`。存入 `{3: 0, 2: 1}`
80+
3. `i = 2, v = 4``complement = 2`。Map 存在 `2`,索引為 `1`
81+
4. 返回 `[1, 2]`。正確。
82+
- **關鍵狀態變遷**
83+
```mermaid
84+
stateDiagram-v2
85+
[*] --> Start
86+
Start --> i0: i=0, v=3, Map={}
87+
i0 --> i1: complement=3 not in Map, Map={3:0}
88+
i1 --> i2: i=1, v=2, complement=4 not in Map, Map={3:0, 2:1}
89+
i2 --> Found: i=2, v=4, complement=2 found in Map!
90+
Found --> [*]
91+
```
7592

7693
### E – Evaluate(總結與評估)
77-
- **時間複雜度**:$O(n)$。我們只需遍歷陣列一次,且每次 Map 的存取與查找均為 $O(1)$。
78-
- **空間複雜度**:$O(n)$。最壞情況下需要將 $n$ 個元素存入 Map。
79-
- **權衡**使用空間換取時間。這是處理「尋找特定配對」問題最經典的優化方式
94+
- **時間複雜度**:$O(n)$。我們只需對陣列進行一次線性掃描,Map 的插入與查找均為 $O(1)$。
95+
- **空間複雜度**:$O(n)$。最壞情況下需要存儲 $n$ 個元素到 Map
96+
- **權衡**我們使用了額外的空間(Hash Map)來換取時間複雜度的大幅提升(從 $O(n^2)$ 優化到 $O(n)$)
8097

8198
---
8299

83100
## Output 2: 面試官口語回答腳本(精簡可直接說)
84101

85102
### 1️⃣ 開場:題目理解
86-
這題是要在陣列中找到兩個數字,讓它們加起來等於目標值 `target`,並回傳這兩個數字的索引。題目保證一定有一個解,且每個數字不能重複使用
103+
這是一道尋找配對的經典問題。題目要求我們在陣列中找到兩個數,其和等於目標值。核心限制是每個數字只能用一次,且保證一定有一個解
87104

88105
### 2️⃣ 解法選擇說明
89-
我選擇使用 **Hash Map** 來解這題,因為它能將尋找「互補數字」的時間從 $O(n)$ 降到 $O(1)$。雖然暴力解用雙層迴圈也能做,但 $O(n^2)$ 的效率在數據量大時會太慢
106+
我選擇使用 **Hash Map** 來解這題,而不是暴力解。因為暴力解的雙層迴圈會導致 $O(n^2)$ 的時間複雜度,而透過 Hash Map,我們可以將搜尋「補數」的時間降到常數級別,整體效率提高到 $O(n)$
90107

91108
### 3️⃣ 解題策略概覽
92-
我會遍歷一次陣列。對於每個數字,我先去計算「還差多少才到 target」,然後檢查這個「差額」是否已經存在 Hash Map 中。如果有,就代表找到了;如果沒有,我就把當前的數字和它的索引存進 Map,繼續往後看
109+
我會遍歷陣列一次。在遍歷到每個數字時,我會先去 Map 裡找看看「還差多少才到目標」。如果有找到,就代表這對數字齊了;如果沒找到,我就把當前的數字和索引記錄下來,讓後面的數字來匹配
93110

94111
### 4️⃣ 寫程式時會補充的關鍵說明
95-
在實作時有兩個細節要注意:
96-
1. 我們要「先檢查、再存入」,這樣可以保證我們不會找到自己,滿足題目「不能重複使用同一個元素」的要求。
97-
2. 在 Golang 中,使用 `if idx, ok := m[complement]; ok` 可以很優雅地同時完成查找和判斷是否存在。
112+
在實作上,順序很重要:我們要「先檢查、後存入」。這樣可以自然地避免「同一個元素被使用兩次」的問題,因為 Map 裡存的永遠是「當前索引之前」的數字。另外,在 Go 語言中,我會利用 `ok` idiom 來檢查 Map 裡是否存在補數。
98113

99114
### 5️⃣ 快速 Dry Run 說明
100-
假設輸入 `[3, 2, 4]` 目標是 `6`
101-
看到 `3` Map 是空的,存入 `{3:0}`
102-
看到 `2` 時去找 `4`,沒找到,存入 `{2:1}`
103-
最後看到 `4` 時去找 `2` Map 裡找到了索引 `1`所以直接回傳 `[1, 2]`
115+
`target = 6`, 陣列 `[3, 2, 4]` 為例
116+
遇到 `3` 的時候,補數是 `3`Map 還是空的,存入 `{3: 0}`
117+
遇到 `2` 的時候,補數是 `4`,沒找到,存入 `{2: 1}`
118+
最後看到 `4` 的時候,補數是 `2`這時在 Map 裡找到了索引 `1`於是成功回傳 `[1, 2]`
104119

105120
### 6️⃣ 收尾總結
106-
這個演算法的**時間複雜度是 $O(n)$****空間複雜度也是 $O(n)$**。這是在這類尋找配對問題中最優的時間效率。
107-
108-
---
121+
這個解法的**時間複雜度是 $O(n)$****空間複雜度也是 $O(n)$**。這是在這類配對搜尋問題中最優的時間效率。

0 commit comments

Comments
 (0)