From 5849ae4ada01d8576cfd283bda95f70c0e3375ff Mon Sep 17 00:00:00 2001 From: Yudong Jin Date: Sat, 28 Sep 2024 09:28:44 +0800 Subject: [PATCH] Sync zh and zh-hant versions. (#1523) --- .../codes/cpp/chapter_sorting/quick_sort.cpp | 53 ++++++------------- .../chapter_array_and_linkedlist/my_list.js | 2 +- .../rust/chapter_backtracking/n_queens.rs | 19 ++----- .../rust/chapter_backtracking/subset_sum_i.rs | 10 ++-- .../subset_sum_i_naive.rs | 10 ++-- .../chapter_backtracking/subset_sum_ii.rs | 10 ++-- zh-hant/codes/rust/include/list_node.rs | 16 +++--- zh-hant/codes/rust/include/tree_node.rs | 22 ++++---- .../linked_list.md | 4 +- zh-hant/docs/chapter_tree/binary_tree.md | 2 +- zh-hant/docs/index.md | 2 +- 11 files changed, 58 insertions(+), 92 deletions(-) diff --git a/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp b/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp index ca7994e2f..99ae48d56 100644 --- a/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp +++ b/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp @@ -9,26 +9,19 @@ /* 快速排序類別 */ class QuickSort { private: - /* 元素交換 */ - static void swap(vector &nums, int i, int j) { - int tmp = nums[i]; - nums[i] = nums[j]; - nums[j] = tmp; - } - /* 哨兵劃分 */ static int partition(vector &nums, int left, int right) { // 以 nums[left] 為基準數 int i = left, j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) - j--; // 從右向左找首個小於基準數的元素 + j--; // 從右向左找首個小於基準數的元素 while (i < j && nums[i] <= nums[left]) - i++; // 從左向右找首個大於基準數的元素 - swap(nums, i, j); // 交換這兩個元素 + i++; // 從左向右找首個大於基準數的元素 + swap(nums[i], nums[j]); // 交換這兩個元素 } - swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 - return i; // 返回基準數的索引 + swap(nums[i], nums[left]); // 將基準數交換至兩子陣列的分界線 + return i; // 返回基準數的索引 } public: @@ -48,13 +41,6 @@ class QuickSort { /* 快速排序類別(中位基準數最佳化) */ class QuickSortMedian { private: - /* 元素交換 */ - static void swap(vector &nums, int i, int j) { - int tmp = nums[i]; - nums[i] = nums[j]; - nums[j] = tmp; - } - /* 選取三個候選元素的中位數 */ static int medianThree(vector &nums, int left, int mid, int right) { int l = nums[left], m = nums[mid], r = nums[right]; @@ -70,18 +56,18 @@ class QuickSortMedian { // 選取三個候選元素的中位數 int med = medianThree(nums, left, (left + right) / 2, right); // 將中位數交換至陣列最左端 - swap(nums, left, med); + swap(nums[left], nums[med]); // 以 nums[left] 為基準數 int i = left, j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) - j--; // 從右向左找首個小於基準數的元素 + j--; // 從右向左找首個小於基準數的元素 while (i < j && nums[i] <= nums[left]) - i++; // 從左向右找首個大於基準數的元素 - swap(nums, i, j); // 交換這兩個元素 + i++; // 從左向右找首個大於基準數的元素 + swap(nums[i], nums[j]); // 交換這兩個元素 } - swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 - return i; // 返回基準數的索引 + swap(nums[i], nums[left]); // 將基準數交換至兩子陣列的分界線 + return i; // 返回基準數的索引 } public: @@ -101,26 +87,19 @@ class QuickSortMedian { /* 快速排序類別(尾遞迴最佳化) */ class QuickSortTailCall { private: - /* 元素交換 */ - static void swap(vector &nums, int i, int j) { - int tmp = nums[i]; - nums[i] = nums[j]; - nums[j] = tmp; - } - /* 哨兵劃分 */ static int partition(vector &nums, int left, int right) { // 以 nums[left] 為基準數 int i = left, j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) - j--; // 從右向左找首個小於基準數的元素 + j--; // 從右向左找首個小於基準數的元素 while (i < j && nums[i] <= nums[left]) - i++; // 從左向右找首個大於基準數的元素 - swap(nums, i, j); // 交換這兩個元素 + i++; // 從左向右找首個大於基準數的元素 + swap(nums[i], nums[j]); // 交換這兩個元素 } - swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 - return i; // 返回基準數的索引 + swap(nums[i], nums[left]); // 將基準數交換至兩子陣列的分界線 + return i; // 返回基準數的索引 } public: diff --git a/zh-hant/codes/javascript/chapter_array_and_linkedlist/my_list.js b/zh-hant/codes/javascript/chapter_array_and_linkedlist/my_list.js index 0018da834..030ba3750 100644 --- a/zh-hant/codes/javascript/chapter_array_and_linkedlist/my_list.js +++ b/zh-hant/codes/javascript/chapter_array_and_linkedlist/my_list.js @@ -70,7 +70,7 @@ class MyList { remove(index) { if (index < 0 || index >= this.#size) throw new Error('索引越界'); let num = this.#arr[index]; - // 將將索引 index 之後的元素都向前移動一位 + // 將索引 index 之後的元素都向前移動一位 for (let j = index; j < this.#size - 1; j++) { this.#arr[j] = this.#arr[j + 1]; } diff --git a/zh-hant/codes/rust/chapter_backtracking/n_queens.rs b/zh-hant/codes/rust/chapter_backtracking/n_queens.rs index b7708f5bc..239ef03fb 100644 --- a/zh-hant/codes/rust/chapter_backtracking/n_queens.rs +++ b/zh-hant/codes/rust/chapter_backtracking/n_queens.rs @@ -16,11 +16,7 @@ fn backtrack( ) { // 當放置完所有行時,記錄解 if row == n { - let mut copy_state: Vec> = Vec::new(); - for s_row in state.clone() { - copy_state.push(s_row); - } - res.push(copy_state); + res.push(state.clone()); return; } // 走訪所有列 @@ -31,12 +27,12 @@ fn backtrack( // 剪枝:不允許該格子所在列、主對角線、次對角線上存在皇后 if !cols[col] && !diags1[diag1] && !diags2[diag2] { // 嘗試:將皇后放置在該格子 - state.get_mut(row).unwrap()[col] = "Q".into(); + state[row][col] = "Q".into(); (cols[col], diags1[diag1], diags2[diag2]) = (true, true, true); // 放置下一行 backtrack(row + 1, n, state, res, cols, diags1, diags2); // 回退:將該格子恢復為空位 - state.get_mut(row).unwrap()[col] = "#".into(); + state[row][col] = "#".into(); (cols[col], diags1[diag1], diags2[diag2]) = (false, false, false); } } @@ -45,14 +41,7 @@ fn backtrack( /* 求解 n 皇后 */ fn n_queens(n: usize) -> Vec>> { // 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位 - let mut state: Vec> = Vec::new(); - for _ in 0..n { - let mut row: Vec = Vec::new(); - for _ in 0..n { - row.push("#".into()); - } - state.push(row); - } + let mut state: Vec> = vec![vec!["#".to_string(); n]; n]; let mut cols = vec![false; n]; // 記錄列是否有皇后 let mut diags1 = vec![false; 2 * n - 1]; // 記錄主對角線上是否有皇后 let mut diags2 = vec![false; 2 * n - 1]; // 記錄次對角線上是否有皇后 diff --git a/zh-hant/codes/rust/chapter_backtracking/subset_sum_i.rs b/zh-hant/codes/rust/chapter_backtracking/subset_sum_i.rs index 86c685ec7..91c1517ae 100644 --- a/zh-hant/codes/rust/chapter_backtracking/subset_sum_i.rs +++ b/zh-hant/codes/rust/chapter_backtracking/subset_sum_i.rs @@ -6,7 +6,7 @@ /* 回溯演算法:子集和 I */ fn backtrack( - mut state: Vec, + state: &mut Vec, target: i32, choices: &[i32], start: usize, @@ -14,7 +14,7 @@ fn backtrack( ) { // 子集和等於 target 時,記錄解 if target == 0 { - res.push(state); + res.push(state.clone()); return; } // 走訪所有選擇 @@ -28,7 +28,7 @@ fn backtrack( // 嘗試:做出選擇,更新 target, start state.push(choices[i]); // 進行下一輪選擇 - backtrack(state.clone(), target - choices[i], choices, i, res); + backtrack(state, target - choices[i], choices, i, res); // 回退:撤銷選擇,恢復到之前的狀態 state.pop(); } @@ -36,11 +36,11 @@ fn backtrack( /* 求解子集和 I */ fn subset_sum_i(nums: &mut [i32], target: i32) -> Vec> { - let state = Vec::new(); // 狀態(子集) + let mut state = Vec::new(); // 狀態(子集) nums.sort(); // 對 nums 進行排序 let start = 0; // 走訪起始點 let mut res = Vec::new(); // 結果串列(子集串列) - backtrack(state, target, nums, start, &mut res); + backtrack(&mut state, target, nums, start, &mut res); res } diff --git a/zh-hant/codes/rust/chapter_backtracking/subset_sum_i_naive.rs b/zh-hant/codes/rust/chapter_backtracking/subset_sum_i_naive.rs index 6b25bbd41..34d8dbfe3 100644 --- a/zh-hant/codes/rust/chapter_backtracking/subset_sum_i_naive.rs +++ b/zh-hant/codes/rust/chapter_backtracking/subset_sum_i_naive.rs @@ -6,7 +6,7 @@ /* 回溯演算法:子集和 I */ fn backtrack( - mut state: Vec, + state: &mut Vec, target: i32, total: i32, choices: &[i32], @@ -14,7 +14,7 @@ fn backtrack( ) { // 子集和等於 target 時,記錄解 if total == target { - res.push(state); + res.push(state.clone()); return; } // 走訪所有選擇 @@ -26,7 +26,7 @@ fn backtrack( // 嘗試:做出選擇,更新元素和 total state.push(choices[i]); // 進行下一輪選擇 - backtrack(state.clone(), target, total + choices[i], choices, res); + backtrack(state, target, total + choices[i], choices, res); // 回退:撤銷選擇,恢復到之前的狀態 state.pop(); } @@ -34,10 +34,10 @@ fn backtrack( /* 求解子集和 I(包含重複子集) */ fn subset_sum_i_naive(nums: &[i32], target: i32) -> Vec> { - let state = Vec::new(); // 狀態(子集) + let mut state = Vec::new(); // 狀態(子集) let total = 0; // 子集和 let mut res = Vec::new(); // 結果串列(子集串列) - backtrack(state, target, total, nums, &mut res); + backtrack(&mut state, target, total, nums, &mut res); res } diff --git a/zh-hant/codes/rust/chapter_backtracking/subset_sum_ii.rs b/zh-hant/codes/rust/chapter_backtracking/subset_sum_ii.rs index 6638ee9fe..6da22c674 100644 --- a/zh-hant/codes/rust/chapter_backtracking/subset_sum_ii.rs +++ b/zh-hant/codes/rust/chapter_backtracking/subset_sum_ii.rs @@ -6,7 +6,7 @@ /* 回溯演算法:子集和 II */ fn backtrack( - mut state: Vec, + state: &mut Vec, target: i32, choices: &[i32], start: usize, @@ -14,7 +14,7 @@ fn backtrack( ) { // 子集和等於 target 時,記錄解 if target == 0 { - res.push(state); + res.push(state.clone()); return; } // 走訪所有選擇 @@ -33,7 +33,7 @@ fn backtrack( // 嘗試:做出選擇,更新 target, start state.push(choices[i]); // 進行下一輪選擇 - backtrack(state.clone(), target - choices[i], choices, i + 1, res); + backtrack(state, target - choices[i], choices, i + 1, res); // 回退:撤銷選擇,恢復到之前的狀態 state.pop(); } @@ -41,11 +41,11 @@ fn backtrack( /* 求解子集和 II */ fn subset_sum_ii(nums: &mut [i32], target: i32) -> Vec> { - let state = Vec::new(); // 狀態(子集) + let mut state = Vec::new(); // 狀態(子集) nums.sort(); // 對 nums 進行排序 let start = 0; // 走訪起始點 let mut res = Vec::new(); // 結果串列(子集串列) - backtrack(state, target, nums, start, &mut res); + backtrack(&mut state, target, nums, start, &mut res); res } diff --git a/zh-hant/codes/rust/include/list_node.rs b/zh-hant/codes/rust/include/list_node.rs index 110382a1a..941e334c3 100644 --- a/zh-hant/codes/rust/include/list_node.rs +++ b/zh-hant/codes/rust/include/list_node.rs @@ -29,7 +29,7 @@ impl ListNode { for item in array.iter().rev() { let node = Rc::new(RefCell::new(ListNode { val: *item, - next: head.clone(), + next: head.take(), })); head = Some(node); } @@ -44,14 +44,14 @@ impl ListNode { T: std::hash::Hash + Eq + Copy + Clone, { let mut hashmap = HashMap::new(); - if let Some(node) = linked_list { - let mut current = Some(node.clone()); - while let Some(cur) = current { - let borrow = cur.borrow(); - hashmap.insert(borrow.val.clone(), cur.clone()); - current = borrow.next.clone(); - } + let mut node = linked_list; + + while let Some(cur) = node { + let borrow = cur.borrow(); + hashmap.insert(borrow.val.clone(), cur.clone()); + node = borrow.next.clone(); } + hashmap } } diff --git a/zh-hant/codes/rust/include/tree_node.rs b/zh-hant/codes/rust/include/tree_node.rs index b561b535a..514491862 100644 --- a/zh-hant/codes/rust/include/tree_node.rs +++ b/zh-hant/codes/rust/include/tree_node.rs @@ -72,23 +72,21 @@ pub fn vec_to_tree(arr: Vec>) -> Option>> { } /* 將二元樹序列化為串列:遞迴 */ -fn tree_to_vec_dfs(root: Option>>, i: usize, res: &mut Vec>) { - if root.is_none() { - return; +fn tree_to_vec_dfs(root: Option<&Rc>>, i: usize, res: &mut Vec>) { + if let Some(root) = root { + // i + 1 is the minimum valid size to access index i + while res.len() < i + 1 { + res.push(None); + } + res[i] = Some(root.borrow().val); + tree_to_vec_dfs(root.borrow().left.as_ref(), 2 * i + 1, res); + tree_to_vec_dfs(root.borrow().right.as_ref(), 2 * i + 2, res); } - let root = root.unwrap(); - // i + 1 is the minimum valid size to access index i - while res.len() < i + 1 { - res.push(None); - } - res[i] = Some(root.borrow().val); - tree_to_vec_dfs(root.borrow().left.clone(), 2 * i + 1, res); - tree_to_vec_dfs(root.borrow().right.clone(), 2 * i + 2, res); } /* 將二元樹序列化為串列 */ pub fn tree_to_vec(root: Option>>) -> Vec> { let mut res = vec![]; - tree_to_vec_dfs(root, 0, &mut res); + tree_to_vec_dfs(root.as_ref(), 0, &mut res); res } diff --git a/zh-hant/docs/chapter_array_and_linkedlist/linked_list.md b/zh-hant/docs/chapter_array_and_linkedlist/linked_list.md index 263ccb02d..218c96776 100755 --- a/zh-hant/docs/chapter_array_and_linkedlist/linked_list.md +++ b/zh-hant/docs/chapter_array_and_linkedlist/linked_list.md @@ -635,8 +635,8 @@ /* 雙向鏈結串列節點類別 */ class ListNode { int val; // 節點值 - ListNode next; // 指向後繼節點的引用 - ListNode prev; // 指向前驅節點的引用 + ListNode? next; // 指向後繼節點的引用 + ListNode? prev; // 指向前驅節點的引用 ListNode(this.val, [this.next, this.prev]); // 建構子 } ``` diff --git a/zh-hant/docs/chapter_tree/binary_tree.md b/zh-hant/docs/chapter_tree/binary_tree.md index 0e0e0de27..69c2820a6 100644 --- a/zh-hant/docs/chapter_tree/binary_tree.md +++ b/zh-hant/docs/chapter_tree/binary_tree.md @@ -651,7 +651,7 @@ ### 完全二元樹 -如下圖所示,完全二元樹(complete binary tree)只有最底層的節點未被填滿,且最底層節點儘量靠左填充。 +如下圖所示,完全二元樹(complete binary tree)只有最底層的節點未被填滿,且最底層節點儘量靠左填充。請注意,完美二元樹也是一棵完全二元樹。 ![完全二元樹](binary_tree.assets/complete_binary_tree.png) diff --git a/zh-hant/docs/index.md b/zh-hant/docs/index.md index 692f2c85e..086cf787f 100644 --- a/zh-hant/docs/index.md +++ b/zh-hant/docs/index.md @@ -1,5 +1,5 @@ # Hello 演算法 -動畫圖解、一鍵執行的資料結構與演算法教程 +動畫圖解、一鍵執行的資料結構與演算法教程。 [開始閱讀](chapter_hello_algo/)