mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-22 03:16:08 +00:00
5.0 KiB
5.0 KiB
練習
知識鞏固
陣列和鏈結串列怎樣找到元素
陣列和單向鏈結串列中都按順序儲存了 [A, B, C, D, E]。現在要讀取第 4 個元素 D:
- 陣列可以直接使用哪個索引?
- 單向鏈結串列從頭節點
A開始,要沿著next依次經過哪些節點? - 當要讀取的元素位置越來越靠後時,兩種結構所需的步驟會怎樣變化?哪一種更適合反覆按位置讀取?為什麼?
??? success "參考答案"
1. 若索引從 0 開始,第 4 個元素的索引是 3,陣列可直接讀取 `arr[3]`。
2. 單向鏈結串列必須從頭開始,訪問路徑為 `A → B → C → D`,需要沿 `next` 前進 3 次。
3. 陣列可以根據首位址和索引直接定位元素,按位置訪問的時間複雜度為 $O(1)$。
單向鏈結串列訪問第 $k$ 個節點時,必須從頭節點開始,沿著 `next` 前進 $k-1$ 次,
最壞需要 $O(n)$ 時間。
這裡只比較按位置讀取,不表示鏈結串列在所有操作上都更慢。
陣列和鏈結串列怎樣插入元素
陣列和單向鏈結串列中都儲存了 A、B、C、D。現在要在 B 後面插入 X:
- 陣列容量為 5,當前狀態是
[A, B, C, D, _]; - 鏈結串列為
A → B → C → D,並且已經拿到了指向節點B的引用。
- 陣列需要移動哪些元素?寫出插入後的陣列。
- 鏈結串列應按什麼順序修改
X.next和B.next?寫出插入後的鏈結串列。 - 為什麼比較插入效率時,要特別說明“已經拿到了節點 B 的引用”?
??? success "參考答案"
1. 陣列要先把 `D` 向右移動一格,再把 `C` 向右移動一格,最後把 `X` 放入索引 2,
得到 `[A, B, X, C, D]`。
2. `B.next` 原本指向 `C`。應先令 `X.next = B.next`,讓 `X` 指向 `C`;
再令 `B.next = X`。結果為 `A → B → X → C → D`。
如果先覆蓋 `B.next` 又沒有儲存原來的連線,就可能找不到 `C`。
3. 已知 `B` 的位置後,鏈結串列插入只需修改兩個連線,可以在 $O(1)$ 時間完成。
如果還要從頭查詢 `B`,查詢過程本身可能需要 $O(n)$ 時間。
串列容量是怎樣增長的
一個基於陣列實現的串列當前內容為 [A, B, C],長度 size = 3,容量 capacity = 4。
規定容量不足時,新陣列的容量擴大為原來的 2 倍。
- 追加
D後,串列的長度和容量分別是多少?是否需要擴容? - 接著追加
E時,容量會變為多少?需要複製幾個原有元素? - 底層陣列的長度不可變,為什麼串列的容量看起來卻可以增長?
??? success "參考答案"
1. `D` 可以放入最後一個空位。此時內容為 `[A, B, C, D]`,
`size = 4`、`capacity = 4`,不需要擴容。
2. 再追加 `E` 時已經沒有空位,需要建立容量為 8 的新陣列,
將 `A、B、C、D` 共 4 個原有元素複製過去,再加入 `E`。
此時 `size = 5`、`capacity = 8`。
3. 原來的陣列本身沒有變長。串列建立了一個更大的新陣列,複製原有元素,
再改用新陣列作為底層儲存,因此對使用者來說容量增長了。
程式設計練習
陣列表示的大整數加一
陣列 digits 從左到右儲存一個非負整數的各位數字,例如 [3, 0, 8] 表示 308。
數字 0 用 [0] 表示;其他輸入的第一位均不為 0。
請模擬一次十進位制豎式加法,將這個整數增加 1,並把結果仍按相同的陣列形式返回。
可以直接修改 digits;若最前面產生新的進位,可以返回一個更長的陣列。
??? tip "解題提示"
1. 像做豎式加法一樣,從陣列最後一位開始
2. 當前位小於 9 時加一後即可立即返回
3. 當前位等於 9 時把它改成 0;若所有位都是 9,需要在最前面補 1
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
反轉單向鏈結串列
給定一個單向鏈結串列的頭節點 head。每個節點包含一個值和指向下一節點的 next。
請使用迭代方法反轉所有節點之間的連線,並返回反轉後的頭節點。 要求不建立新的鏈結串列節點。
??? tip "解題提示"
1. 先在紙上畫出三個相連的節點和 prev、cur 兩個指標
2. 改寫 cur.next 前,必須先用 nxt 儲存原來的下一個節點
3. 反轉 cur.next 後,令 prev = cur,再令 cur = nxt,繼續處理原鏈結串列中的下一個節點
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" } 題目解析{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }