diff --git a/zh-hant/codes/c/chapter_hashing/simple_hash.c b/zh-hant/codes/c/chapter_hashing/simple_hash.c index 05d21e7b3..4d2fdcf33 100644 --- a/zh-hant/codes/c/chapter_hashing/simple_hash.c +++ b/zh-hant/codes/c/chapter_hashing/simple_hash.c @@ -50,7 +50,7 @@ int rotHash(char *key) { /* Driver Code */ int main() { - char *key = "Hello dsad3241241dsa算123法"; + char *key = "Hello 演算法"; int hash = addHash(key); printf("加法雜湊值為 %d\n", hash); diff --git a/zh-hant/codes/c/chapter_stack_and_queue/array_stack.c b/zh-hant/codes/c/chapter_stack_and_queue/array_stack.c index d70cab7f8..4593c6ba1 100644 --- a/zh-hant/codes/c/chapter_stack_and_queue/array_stack.c +++ b/zh-hant/codes/c/chapter_stack_and_queue/array_stack.c @@ -90,11 +90,11 @@ int main() { /* 獲取堆疊的長度 */ int size = stack->size; - printf("堆疊的長度 size = %d\n", size); + printf("堆疊的長度 size = %d\n", size); /* 判斷是否為空 */ bool empty = isEmpty(stack); - printf("堆疊是否為空 = %stack\n", empty ? "true" : "false"); + printf("堆疊是否為空 = %s\n", empty ? "true" : "false"); // 釋放記憶體 delArrayStack(stack); diff --git a/zh-hant/codes/cpp/chapter_hashing/simple_hash.cpp b/zh-hant/codes/cpp/chapter_hashing/simple_hash.cpp index 2b43e166a..b8a3173a6 100644 --- a/zh-hant/codes/cpp/chapter_hashing/simple_hash.cpp +++ b/zh-hant/codes/cpp/chapter_hashing/simple_hash.cpp @@ -48,7 +48,7 @@ int rotHash(string key) { /* Driver Code */ int main() { - string key = "Hello dsad3241241dsa算123法"; + string key = "Hello 演算法"; int hash = addHash(key); cout << "加法雜湊值為 " << hash << endl; diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change.js b/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change.js index 27660a9a0..0d6aca277 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change.js @@ -31,7 +31,7 @@ function coinChangeDP(coins, amt) { return dp[n][amt] !== MAX ? dp[n][amt] : -1; } -/* 零錢兌換:狀態壓縮後的動態規劃 */ +/* 零錢兌換:空間最佳化後的動態規劃 */ function coinChangeDPComp(coins, amt) { const n = coins.length; const MAX = amt + 1; @@ -61,6 +61,6 @@ const amt = 4; let res = coinChangeDP(coins, amt); console.log(`湊到目標金額所需的最少硬幣數量為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = coinChangeDPComp(coins, amt); console.log(`湊到目標金額所需的最少硬幣數量為 ${res}`); diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change_ii.js b/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change_ii.js index c4346524d..39edcb6df 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change_ii.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/coin_change_ii.js @@ -30,7 +30,7 @@ function coinChangeIIDP(coins, amt) { return dp[n][amt]; } -/* 零錢兌換 II:狀態壓縮後的動態規劃 */ +/* 零錢兌換 II:空間最佳化後的動態規劃 */ function coinChangeIIDPComp(coins, amt) { const n = coins.length; // 初始化 dp 表 @@ -59,6 +59,6 @@ const amt = 5; let res = coinChangeIIDP(coins, amt); console.log(`湊出目標金額的硬幣組合數量為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = coinChangeIIDPComp(coins, amt); console.log(`湊出目標金額的硬幣組合數量為 ${res}`); diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/edit_distance.js b/zh-hant/codes/javascript/chapter_dynamic_programming/edit_distance.js index 0a121c5d7..fccb443a3 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/edit_distance.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/edit_distance.js @@ -82,7 +82,7 @@ function editDistanceDP(s, t) { return dp[n][m]; } -/* 編輯距離:狀態壓縮後的動態規劃 */ +/* 編輯距離:空間最佳化後的動態規劃 */ function editDistanceDPComp(s, t) { const n = s.length, m = t.length; @@ -130,6 +130,6 @@ console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); res = editDistanceDP(s, t); console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = editDistanceDPComp(s, t); console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/knapsack.js b/zh-hant/codes/javascript/chapter_dynamic_programming/knapsack.js index 54f112200..9bcd4727a 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/knapsack.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/knapsack.js @@ -69,7 +69,7 @@ function knapsackDP(wgt, val, cap) { return dp[n][cap]; } -/* 0-1 背包:狀態壓縮後的動態規劃 */ +/* 0-1 背包:空間最佳化後的動態規劃 */ function knapsackDPComp(wgt, val, cap) { const n = wgt.length; // 初始化 dp 表 @@ -108,6 +108,6 @@ console.log(`不超過背包容量的最大物品價值為 ${res}`); res = knapsackDP(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = knapsackDPComp(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.js b/zh-hant/codes/javascript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.js index 7f63d01d6..7224d5a3c 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.js @@ -22,7 +22,7 @@ function minCostClimbingStairsDP(cost) { return dp[n]; } -/* 爬樓梯最小代價:狀態壓縮後的動態規劃 */ +/* 爬樓梯最小代價:空間最佳化後的動態規劃 */ function minCostClimbingStairsDPComp(cost) { const n = cost.length - 1; if (n === 1 || n === 2) { diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/min_path_sum.js b/zh-hant/codes/javascript/chapter_dynamic_programming/min_path_sum.js index a1b2f9855..bd49d9f60 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/min_path_sum.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/min_path_sum.js @@ -69,7 +69,7 @@ function minPathSumDP(grid) { return dp[n - 1][m - 1]; } -/* 最小路徑和:狀態壓縮後的動態規劃 */ +/* 最小路徑和:空間最佳化後的動態規劃 */ function minPathSumDPComp(grid) { const n = grid.length, m = grid[0].length; @@ -116,6 +116,6 @@ console.log(`從左上角到右下角的最小路徑和為 ${res}`); res = minPathSumDP(grid); console.log(`從左上角到右下角的最小路徑和為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = minPathSumDPComp(grid); console.log(`從左上角到右下角的最小路徑和為 ${res}`); diff --git a/zh-hant/codes/javascript/chapter_dynamic_programming/unbounded_knapsack.js b/zh-hant/codes/javascript/chapter_dynamic_programming/unbounded_knapsack.js index f7f504c54..f5c48c8c1 100644 --- a/zh-hant/codes/javascript/chapter_dynamic_programming/unbounded_knapsack.js +++ b/zh-hant/codes/javascript/chapter_dynamic_programming/unbounded_knapsack.js @@ -29,7 +29,7 @@ function unboundedKnapsackDP(wgt, val, cap) { return dp[n][cap]; } -/* 完全背包:狀態壓縮後的動態規劃 */ +/* 完全背包:空間最佳化後的動態規劃 */ function unboundedKnapsackDPComp(wgt, val, cap) { const n = wgt.length; // 初始化 dp 表 @@ -58,6 +58,6 @@ const cap = 4; let res = unboundedKnapsackDP(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = unboundedKnapsackDPComp(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); diff --git a/zh-hant/codes/ruby/chapter_divide_and_conquer/binary_search_recur.rb b/zh-hant/codes/ruby/chapter_divide_and_conquer/binary_search_recur.rb new file mode 100644 index 000000000..5a624bac4 --- /dev/null +++ b/zh-hant/codes/ruby/chapter_divide_and_conquer/binary_search_recur.rb @@ -0,0 +1,42 @@ +=begin +File: binary_search_recur.rb +Created Time: 2024-05-13 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 二分搜尋:問題 f(i, j) ### +def dfs(nums, target, i, j) + # 若區間為空,代表無目標元素,則返回 -1 + return -1 if i > j + + # 計算中點索引 m + m = (i + j) / 2 + + if nums[m] < target + # 遞迴子問題 f(m+1, j) + return dfs(nums, target, m + 1, j) + elsif nums[m] > target + # 遞迴子問題 f(i, m-1) + return dfs(nums, target, i, m - 1) + else + # 找到目標元素,返回其索引 + return m + end +end + +### 二分搜尋 ### +def binary_search(nums, target) + n = nums.length + # 求解問題 f(0, n-1) + dfs(nums, target, 0, n - 1) +end + +### Driver Code ### +if __FILE__ == $0 + target = 6 + nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35] + + # 二分搜尋(雙閉區間) + index = binary_search(nums, target) + puts "目標元素 6 的索引 = #{index}" +end diff --git a/zh-hant/codes/ruby/chapter_divide_and_conquer/build_tree.rb b/zh-hant/codes/ruby/chapter_divide_and_conquer/build_tree.rb new file mode 100644 index 000000000..2ffdbaf07 --- /dev/null +++ b/zh-hant/codes/ruby/chapter_divide_and_conquer/build_tree.rb @@ -0,0 +1,46 @@ +=begin +File: build_tree.rb +Created Time: 2024-05-13 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +require_relative '../utils/tree_node' +require_relative '../utils/print_util' + +### 構建二元樹:分治 ### +def dfs(preorder, inorder_map, i, l, r) + # 子樹區間為空時終止 + return if r - l < 0 + + # 初始化根節點 + root = TreeNode.new(preorder[i]) + # 查詢 m ,從而劃分左右子樹 + m = inorder_map[preorder[i]] + # 子問題:構建左子樹 + root.left = dfs(preorder, inorder_map, i + 1, l, m - 1) + # 子問題:構建右子樹 + root.right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r) + + # 返回根節點 + root +end + +### 構建二元樹 ### +def build_tree(preorder, inorder) + # 初始化雜湊表,儲存 inorder 元素到索引的對映 + inorder_map = {} + inorder.each_with_index { |val, i| inorder_map[val] = i } + dfs(preorder, inorder_map, 0, 0, inorder.length - 1) +end + +### Driver Code ### +if __FILE__ == $0 + preorder = [3, 9, 2, 1, 7] + inorder = [9, 3, 1, 2, 7] + puts "前序走訪 = #{preorder}" + puts "中序走訪 = #{inorder}" + + root = build_tree(preorder, inorder) + puts "構建的二元樹為:" + print_tree(root) +end diff --git a/zh-hant/codes/ruby/chapter_divide_and_conquer/hanota.rb b/zh-hant/codes/ruby/chapter_divide_and_conquer/hanota.rb new file mode 100644 index 000000000..e68a64bf4 --- /dev/null +++ b/zh-hant/codes/ruby/chapter_divide_and_conquer/hanota.rb @@ -0,0 +1,55 @@ +=begin +File: hanota.rb +Created Time: 2024-05-13 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 移動一個圓盤 ### +def move(src, tar) + # 從 src 頂部拿出一個圓盤 + pan = src.pop + # 將圓盤放入 tar 頂部 + tar << pan +end + +### 求解河內塔問題 f(i) ### +def dfs(i, src, buf, tar) + # 若 src 只剩下一個圓盤,則直接將其移到 tar + if i == 1 + move(src, tar) + return + end + + # 子問題 f(i-1) :將 src 頂部 i-1 個圓盤藉助 tar 移到 buf + dfs(i - 1, src, tar, buf) + # 子問題 f(1) :將 src 剩餘一個圓盤移到 tar + move(src, tar) + # 子問題 f(i-1) :將 buf 頂部 i-1 個圓盤藉助 src 移到 tar + dfs(i - 1, buf, src, tar) +end + +### 求解河內塔問題 ### +def solve_hanota(_A, _B, _C) + n = _A.length + # 將 A 頂部 n 個圓盤藉助 B 移到 C + dfs(n, _A, _B, _C) +end + +### Driver Code ### +if __FILE__ == $0 + # 串列尾部是柱子頂部 + A = [5, 4, 3, 2, 1] + B = [] + C = [] + puts "初始狀態下:" + puts "A = #{A}" + puts "B = #{B}" + puts "C = #{C}" + + solve_hanota(A, B, C) + + puts "圓盤移動完成後:" + puts "A = #{A}" + puts "B = #{B}" + puts "C = #{C}" +end diff --git a/zh-hant/codes/ruby/chapter_greedy/coin_change_greedy.rb b/zh-hant/codes/ruby/chapter_greedy/coin_change_greedy.rb new file mode 100644 index 000000000..513d15eb7 --- /dev/null +++ b/zh-hant/codes/ruby/chapter_greedy/coin_change_greedy.rb @@ -0,0 +1,50 @@ +=begin +File: coin_change_greedy.rb +Created Time: 2024-05-07 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 零錢兌換:貪婪 ### +def coin_change_greedy(coins, amt) + # 假設 coins 串列有序 + i = coins.length - 1 + count = 0 + # 迴圈進行貪婪選擇,直到無剩餘金額 + while amt > 0 + # 找到小於且最接近剩餘金額的硬幣 + while i > 0 && coins[i] > amt + i -= 1 + end + # 選擇 coins[i] + amt -= coins[i] + count += 1 + end + # 若未找到可行方案, 則返回 -1 + amt == 0 ? count : -1 +end + +### Driver Code ### +if __FILE__ == $0 + # 貪婪:能夠保證找到全域性最優解 + coins = [1, 5, 10, 20, 50, 100] + amt = 186 + res = coin_change_greedy(coins, amt) + puts "\ncoins = #{coins}, amt = #{amt}" + puts "湊到 #{amt} 所需的最少硬幣數量為 #{res}" + + # 貪婪:無法保證找到全域性最優解 + coins = [1, 20, 50] + amt = 60 + res = coin_change_greedy(coins, amt) + puts "\ncoins = #{coins}, amt = #{amt}" + puts "湊到 #{amt} 所需的最少硬幣數量為 #{res}" + puts "實際上需要的最少數量為 3 , 即 20 + 20 + 20" + + # 貪婪:無法保證找到全域性最優解 + coins = [1, 49, 50] + amt = 98 + res = coin_change_greedy(coins, amt) + puts "\ncoins = #{coins}, amt = #{amt}" + puts "湊到 #{amt} 所需的最少硬幣數量為 #{res}" + puts "實際上需要的最少數量為 2 , 即 49 + 49" +end diff --git a/zh-hant/codes/ruby/chapter_greedy/fractional_knapsack.rb b/zh-hant/codes/ruby/chapter_greedy/fractional_knapsack.rb new file mode 100644 index 000000000..838954cca --- /dev/null +++ b/zh-hant/codes/ruby/chapter_greedy/fractional_knapsack.rb @@ -0,0 +1,51 @@ +=begin +File: fractional_knapsack.rb +Created Time: 2024-05-07 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 物品 ### +class Item + attr_accessor :w # 物品重量 + attr_accessor :v # 物品價值 + + def initialize(w, v) + @w = w + @v = v + end +end + +### 分數背包:貪婪 ### +def fractional_knapsack(wgt, val, cap) + # 建立物品串列,包含兩個屬性:重量,價值 + items = wgt.each_with_index.map { |w, i| Item.new(w, val[i]) } + # 按照單位價值 item.v / item.w 從高到低進行排序 + items.sort! { |a, b| (b.v.to_f / b.w) <=> (a.v.to_f / a.w) } + # 迴圈貪婪選擇 + res = 0 + for item in items + if item.w <= cap + # 若剩餘容量充足,則將當前物品整個裝進背包 + res += item.v + cap -= item.w + else + # 若剩餘容量不足,則將當前物品的一部分裝進背包 + res += (item.v.to_f / item.w) * cap + # 已無剩餘容量,因此跳出迴圈 + break + end + end + res +end + +### Driver Code ### +if __FILE__ == $0 + wgt = [10, 20, 30, 40, 50] + val = [50, 120, 150, 210, 240] + cap = 50 + n = wgt.length + + # 貪婪演算法 + res = fractional_knapsack(wgt, val, cap) + puts "不超過背包容量的最大物品價值為 #{res}" +end diff --git a/zh-hant/codes/ruby/chapter_greedy/max_capacity.rb b/zh-hant/codes/ruby/chapter_greedy/max_capacity.rb new file mode 100644 index 000000000..ab826c58b --- /dev/null +++ b/zh-hant/codes/ruby/chapter_greedy/max_capacity.rb @@ -0,0 +1,37 @@ +=begin +File: max_capacity.rb +Created Time: 2024-05-07 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 最大容量:貪婪 ### +def max_capacity(ht) + # 初始化 i, j,使其分列陣列兩端 + i, j = 0, ht.length - 1 + # 初始最大容量為 0 + res = 0 + + # 迴圈貪婪選擇,直至兩板相遇 + while i < j + # 更新最大容量 + cap = [ht[i], ht[j]].min * (j - i) + res = [res, cap].max + # 向內移動短板 + if ht[i] < ht[j] + i += 1 + else + j -= 1 + end + end + + res +end + +### Driver Code ### +if __FILE__ == $0 + ht = [3, 8, 5, 2, 7, 7, 3, 4] + + # 貪婪演算法 + res = max_capacity(ht) + puts "最大容量為 #{res}" +end diff --git a/zh-hant/codes/ruby/chapter_greedy/max_product_cutting.rb b/zh-hant/codes/ruby/chapter_greedy/max_product_cutting.rb new file mode 100644 index 000000000..eba81d601 --- /dev/null +++ b/zh-hant/codes/ruby/chapter_greedy/max_product_cutting.rb @@ -0,0 +1,28 @@ +=begin +File: max_product_cutting.rb +Created Time: 2024-05-07 +Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) +=end + +### 最大切分乘積:貪婪 ### +def max_product_cutting(n) + # 當 n <= 3 時,必須切分出一個 1 + return 1 * (n - 1) if n <= 3 + # 貪婪地切分出 3 ,a 為 3 的個數,b 為餘數 + a, b = n / 3, n % 3 + # 當餘數為 1 時,將一對 1 * 3 轉化為 2 * 2 + return (3.pow(a - 1) * 2 * 2).to_i if b == 1 + # 當餘數為 2 時,不做處理 + return (3.pow(a) * 2).to_i if b == 2 + # 當餘數為 0 時,不做處理 + 3.pow(a).to_i +end + +### Driver Code ### +if __FILE__ == $0 + n = 58 + + # 貪婪演算法 + res = max_product_cutting(n) + puts "最大切分乘積為 #{res}" +end diff --git a/zh-hant/codes/rust/chapter_array_and_linkedlist/array.rs b/zh-hant/codes/rust/chapter_array_and_linkedlist/array.rs index 519bc711b..f7805441e 100644 --- a/zh-hant/codes/rust/chapter_array_and_linkedlist/array.rs +++ b/zh-hant/codes/rust/chapter_array_and_linkedlist/array.rs @@ -77,9 +77,9 @@ fn main() { let slice: &[i32] = &[0; 5]; print!("陣列 arr = "); print_util::print_array(&arr); - // 在 Rust 中,指定長度时([i32; 5])爲陣列,不指定長度時(&[i32])爲切片 + // 在 Rust 中,指定長度時([i32; 5])為陣列,不指定長度時(&[i32])為切片 // 由於 Rust 的陣列被設計為在編譯期確定長度,因此只能使用常數來指定長度 - // Vector 是 Rust 一般情況下用作動態陣列的類型 + // Vector 是 Rust 一般情況下用作動態陣列的型別 // 為了方便實現擴容 extend() 方法,以下將 vector 看作陣列(array) let nums: Vec = vec![1, 3, 2, 5, 4]; print!("\n陣列 nums = "); diff --git a/zh-hant/codes/rust/chapter_divide_and_conquer/hanota.rs b/zh-hant/codes/rust/chapter_divide_and_conquer/hanota.rs index ccdd77a31..7b7649924 100644 --- a/zh-hant/codes/rust/chapter_divide_and_conquer/hanota.rs +++ b/zh-hant/codes/rust/chapter_divide_and_conquer/hanota.rs @@ -9,7 +9,7 @@ /* 移動一個圓盤 */ fn move_pan(src: &mut Vec, tar: &mut Vec) { // 從 src 頂部拿出一個圓盤 - let pan = src.remove(src.len() - 1); + let pan = src.pop().unwrap(); // 將圓盤放入 tar 頂部 tar.push(pan); } diff --git a/zh-hant/codes/rust/chapter_sorting/bubble_sort.rs b/zh-hant/codes/rust/chapter_sorting/bubble_sort.rs index 576b76baf..f68602589 100644 --- a/zh-hant/codes/rust/chapter_sorting/bubble_sort.rs +++ b/zh-hant/codes/rust/chapter_sorting/bubble_sort.rs @@ -14,9 +14,7 @@ fn bubble_sort(nums: &mut [i32]) { for j in 0..i { if nums[j] > nums[j + 1] { // 交換 nums[j] 與 nums[j + 1] - let tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; + nums.swap(j, j + 1); } } } @@ -31,9 +29,7 @@ fn bubble_sort_with_flag(nums: &mut [i32]) { for j in 0..i { if nums[j] > nums[j + 1] { // 交換 nums[j] 與 nums[j + 1] - let tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; + nums.swap(j, j + 1); flag = true; // 記錄交換元素 } } diff --git a/zh-hant/codes/rust/chapter_sorting/bucket_sort.rs b/zh-hant/codes/rust/chapter_sorting/bucket_sort.rs index 27c4ef2cd..c85d64f87 100644 --- a/zh-hant/codes/rust/chapter_sorting/bucket_sort.rs +++ b/zh-hant/codes/rust/chapter_sorting/bucket_sort.rs @@ -12,7 +12,7 @@ fn bucket_sort(nums: &mut [f64]) { let k = nums.len() / 2; let mut buckets = vec![vec![]; k]; // 1. 將陣列元素分配到各個桶中 - for &mut num in &mut *nums { + for &num in nums.iter() { // 輸入資料範圍為 [0, 1),使用 num * k 對映到索引範圍 [0, k-1] let i = (num * k as f64) as usize; // 將 num 新增進桶 i @@ -25,8 +25,8 @@ fn bucket_sort(nums: &mut [f64]) { } // 3. 走訪桶合併結果 let mut i = 0; - for bucket in &mut buckets { - for &mut num in bucket { + for bucket in buckets.iter() { + for &num in bucket.iter() { nums[i] = num; i += 1; } diff --git a/zh-hant/codes/rust/chapter_sorting/counting_sort.rs b/zh-hant/codes/rust/chapter_sorting/counting_sort.rs index 169c30e86..e854b88bb 100644 --- a/zh-hant/codes/rust/chapter_sorting/counting_sort.rs +++ b/zh-hant/codes/rust/chapter_sorting/counting_sort.rs @@ -10,11 +10,11 @@ include!("../include/include.rs"); // 簡單實現,無法用於排序物件 fn counting_sort_naive(nums: &mut [i32]) { // 1. 統計陣列最大元素 m - let m = *nums.into_iter().max().unwrap(); + let m = *nums.iter().max().unwrap(); // 2. 統計各數字的出現次數 // counter[num] 代表 num 的出現次數 let mut counter = vec![0; m as usize + 1]; - for &num in &*nums { + for &num in nums.iter() { counter[num as usize] += 1; } // 3. 走訪 counter ,將各元素填入原陣列 nums @@ -31,16 +31,16 @@ fn counting_sort_naive(nums: &mut [i32]) { // 完整實現,可排序物件,並且是穩定排序 fn counting_sort(nums: &mut [i32]) { // 1. 統計陣列最大元素 m - let m = *nums.into_iter().max().unwrap(); + let m = *nums.iter().max().unwrap() as usize; // 2. 統計各數字的出現次數 // counter[num] 代表 num 的出現次數 - let mut counter = vec![0; m as usize + 1]; - for &num in &*nums { + let mut counter = vec![0; m + 1]; + for &num in nums.iter() { counter[num as usize] += 1; } // 3. 求 counter 的前綴和,將“出現次數”轉換為“尾索引” // 即 counter[num]-1 是 num 在 res 中最後一次出現的索引 - for i in 0..m as usize { + for i in 0..m { counter[i + 1] += counter[i]; } // 4. 倒序走訪 nums ,將各元素填入結果陣列 res @@ -53,9 +53,7 @@ fn counting_sort(nums: &mut [i32]) { counter[num as usize] -= 1; // 令前綴和自減 1 ,得到下次放置 num 的索引 } // 使用結果陣列 res 覆蓋原陣列 nums - for i in 0..n { - nums[i] = res[i]; - } + nums.copy_from_slice(&res) } /* Driver Code */ diff --git a/zh-hant/codes/rust/chapter_sorting/heap_sort.rs b/zh-hant/codes/rust/chapter_sorting/heap_sort.rs index 83cfe0c6b..2d71c348c 100644 --- a/zh-hant/codes/rust/chapter_sorting/heap_sort.rs +++ b/zh-hant/codes/rust/chapter_sorting/heap_sort.rs @@ -24,9 +24,7 @@ fn sift_down(nums: &mut [i32], n: usize, mut i: usize) { break; } // 交換兩節點 - let temp = nums[i]; - nums[i] = nums[ma]; - nums[ma] = temp; + nums.swap(i, ma); // 迴圈向下堆積化 i = ma; } @@ -35,15 +33,13 @@ fn sift_down(nums: &mut [i32], n: usize, mut i: usize) { /* 堆積排序 */ fn heap_sort(nums: &mut [i32]) { // 建堆積操作:堆積化除葉節點以外的其他所有節點 - for i in (0..=nums.len() / 2 - 1).rev() { + for i in (0..nums.len() / 2).rev() { sift_down(nums, nums.len(), i); } // 從堆積中提取最大元素,迴圈 n-1 輪 - for i in (1..=nums.len() - 1).rev() { + for i in (1..nums.len()).rev() { // 交換根節點與最右葉節點(交換首元素與尾元素) - let tmp = nums[0]; - nums[0] = nums[i]; - nums[i] = tmp; + nums.swap(0, i); // 以根節點為起點,從頂至底進行堆積化 sift_down(nums, i, 0); } diff --git a/zh-hant/codes/rust/include/vertex.rs b/zh-hant/codes/rust/include/vertex.rs index b17bef164..6d9b5e550 100644 --- a/zh-hant/codes/rust/include/vertex.rs +++ b/zh-hant/codes/rust/include/vertex.rs @@ -7,7 +7,7 @@ /* 頂點型別 */ #[derive(Copy, Clone, Hash, PartialEq, Eq)] pub struct Vertex { - pub val: i32 + pub val: i32, } /* 輸入值串列 vals ,返回頂點串列 vets */ @@ -18,4 +18,4 @@ pub fn vals_to_vets(vals: Vec) -> Vec { /* 輸入頂點串列 vets ,返回值串列 vals */ pub fn vets_to_vals(vets: Vec) -> Vec { vets.into_iter().map(|vet| vet.val).collect() -} \ No newline at end of file +} diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change.ts index 222ff7ecb..6fe7c251c 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change.ts @@ -31,7 +31,7 @@ function coinChangeDP(coins: Array, amt: number): number { return dp[n][amt] !== MAX ? dp[n][amt] : -1; } -/* 零錢兌換:狀態壓縮後的動態規劃 */ +/* 零錢兌換:空間最佳化後的動態規劃 */ function coinChangeDPComp(coins: Array, amt: number): number { const n = coins.length; const MAX = amt + 1; @@ -61,7 +61,7 @@ const amt = 4; let res = coinChangeDP(coins, amt); console.log(`湊到目標金額所需的最少硬幣數量為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = coinChangeDPComp(coins, amt); console.log(`湊到目標金額所需的最少硬幣數量為 ${res}`); diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change_ii.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change_ii.ts index 0c1376918..fa41017a7 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change_ii.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/coin_change_ii.ts @@ -30,7 +30,7 @@ function coinChangeIIDP(coins: Array, amt: number): number { return dp[n][amt]; } -/* 零錢兌換 II:狀態壓縮後的動態規劃 */ +/* 零錢兌換 II:空間最佳化後的動態規劃 */ function coinChangeIIDPComp(coins: Array, amt: number): number { const n = coins.length; // 初始化 dp 表 @@ -59,7 +59,7 @@ const amt = 5; let res = coinChangeIIDP(coins, amt); console.log(`湊出目標金額的硬幣組合數量為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = coinChangeIIDPComp(coins, amt); console.log(`湊出目標金額的硬幣組合數量為 ${res}`); diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/edit_distance.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/edit_distance.ts index de304b070..906d662aa 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/edit_distance.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/edit_distance.ts @@ -90,7 +90,7 @@ function editDistanceDP(s: string, t: string): number { return dp[n][m]; } -/* 編輯距離:狀態壓縮後的動態規劃 */ +/* 編輯距離:空間最佳化後的動態規劃 */ function editDistanceDPComp(s: string, t: string): number { const n = s.length, m = t.length; @@ -141,7 +141,7 @@ console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); res = editDistanceDP(s, t); console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = editDistanceDPComp(s, t); console.log(`將 ${s} 更改為 ${t} 最少需要編輯 ${res} 步`); diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/knapsack.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/knapsack.ts index 310c876fa..ea23a6cba 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/knapsack.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/knapsack.ts @@ -84,7 +84,7 @@ function knapsackDP( return dp[n][cap]; } -/* 0-1 背包:狀態壓縮後的動態規劃 */ +/* 0-1 背包:空間最佳化後的動態規劃 */ function knapsackDPComp( wgt: Array, val: Array, @@ -127,7 +127,7 @@ console.log(`不超過背包容量的最大物品價值為 ${res}`); res = knapsackDP(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = knapsackDPComp(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.ts index 66980475d..bdeaca596 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/min_cost_climbing_stairs_dp.ts @@ -22,7 +22,7 @@ function minCostClimbingStairsDP(cost: Array): number { return dp[n]; } -/* 爬樓梯最小代價:狀態壓縮後的動態規劃 */ +/* 爬樓梯最小代價:空間最佳化後的動態規劃 */ function minCostClimbingStairsDPComp(cost: Array): number { const n = cost.length - 1; if (n === 1 || n === 2) { diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/min_path_sum.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/min_path_sum.ts index cb1d7ece5..5316095f6 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/min_path_sum.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/min_path_sum.ts @@ -78,7 +78,7 @@ function minPathSumDP(grid: Array>): number { return dp[n - 1][m - 1]; } -/* 最小路徑和:狀態壓縮後的動態規劃 */ +/* 最小路徑和:空間最佳化後的動態規劃 */ function minPathSumDPComp(grid: Array>): number { const n = grid.length, m = grid[0].length; @@ -125,7 +125,7 @@ console.log(`從左上角到右下角的最小路徑和為 ${res}`); res = minPathSumDP(grid); console.log(`從左上角到右下角的最小路徑和為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = minPathSumDPComp(grid); console.log(`從左上角到右下角的最小路徑和為 ${res}`); diff --git a/zh-hant/codes/typescript/chapter_dynamic_programming/unbounded_knapsack.ts b/zh-hant/codes/typescript/chapter_dynamic_programming/unbounded_knapsack.ts index 2e3b4989e..6f0f3ca31 100644 --- a/zh-hant/codes/typescript/chapter_dynamic_programming/unbounded_knapsack.ts +++ b/zh-hant/codes/typescript/chapter_dynamic_programming/unbounded_knapsack.ts @@ -33,7 +33,7 @@ function unboundedKnapsackDP( return dp[n][cap]; } -/* 完全背包:狀態壓縮後的動態規劃 */ +/* 完全背包:空間最佳化後的動態規劃 */ function unboundedKnapsackDPComp( wgt: Array, val: Array, @@ -66,7 +66,7 @@ const cap = 4; let res = unboundedKnapsackDP(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); -// 狀態壓縮後的動態規劃 +// 空間最佳化後的動態規劃 res = unboundedKnapsackDPComp(wgt, val, cap); console.log(`不超過背包容量的最大物品價值為 ${res}`); diff --git a/zh-hant/docs/chapter_array_and_linkedlist/array.md b/zh-hant/docs/chapter_array_and_linkedlist/array.md index c849a642d..823d0103b 100755 --- a/zh-hant/docs/chapter_array_and_linkedlist/array.md +++ b/zh-hant/docs/chapter_array_and_linkedlist/array.md @@ -95,9 +95,9 @@ /* 初始化陣列 */ let arr: [i32; 5] = [0; 5]; // [0, 0, 0, 0, 0] let slice: &[i32] = &[0; 5]; - // 在 Rust 中,指定長度时([i32; 5])爲陣列,不指定長度時(&[i32])爲切片 + // 在 Rust 中,指定長度時([i32; 5])為陣列,不指定長度時(&[i32])為切片 // 由於 Rust 的陣列被設計為在編譯期確定長度,因此只能使用常數來指定長度 - // Vector 是 Rust 一般情況下用作動態陣列的類型 + // Vector 是 Rust 一般情況下用作動態陣列的型別 // 為了方便實現擴容 extend() 方法,以下將 vector 看作陣列(array) let nums: Vec = vec![1, 3, 2, 5, 4]; ``` diff --git a/zh-hant/docs/chapter_array_and_linkedlist/summary.md b/zh-hant/docs/chapter_array_and_linkedlist/summary.md index 41d7c3559..8b0e49635 100644 --- a/zh-hant/docs/chapter_array_and_linkedlist/summary.md +++ b/zh-hant/docs/chapter_array_and_linkedlist/summary.md @@ -73,4 +73,4 @@ **Q**:初始化串列 `res = [0] * self.size()` 操作,會導致 `res` 的每個元素引用相同的位址嗎? -不會。但二維陣列會有這個問題,例如初始化二維串列 `res = [[0] * self.size()]` ,則多次引用了同一個串列 `[0]` 。 +不會。但二維陣列會有這個問題,例如初始化二維串列 `res = [[0]] * self.size()` ,則多次引用了同一個串列 `[0]` 。 diff --git a/zh-hant/docs/chapter_heap/heap.md b/zh-hant/docs/chapter_heap/heap.md index cf7ecb9ee..8f18f33d8 100644 --- a/zh-hant/docs/chapter_heap/heap.md +++ b/zh-hant/docs/chapter_heap/heap.md @@ -533,6 +533,6 @@ ## 堆積的常見應用 -- **優先佇列**:堆積通常作為實現優先佇列的首選資料結構,其入列和出列操作的時間複雜度均為 $O(\log n)$ ,而建隊操作為 $O(n)$ ,這些操作都非常高效。 +- **優先佇列**:堆積通常作為實現優先佇列的首選資料結構,其入列和出列操作的時間複雜度均為 $O(\log n)$ ,而建堆積操作為 $O(n)$ ,這些操作都非常高效。 - **堆積排序**:給定一組資料,我們可以用它們建立一個堆積,然後不斷地執行元素出堆積操作,從而得到有序資料。然而,我們通常會使用一種更優雅的方式實現堆積排序,詳見“堆積排序”章節。 - **獲取最大的 $k$ 個元素**:這是一個經典的演算法問題,同時也是一種典型應用,例如選擇熱度前 10 的新聞作為微博熱搜,選取銷量前 10 的商品等。 diff --git a/zh-hant/docs/chapter_introduction/what_is_dsa.md b/zh-hant/docs/chapter_introduction/what_is_dsa.md index 953b0b7a6..24d5db0e4 100644 --- a/zh-hant/docs/chapter_introduction/what_is_dsa.md +++ b/zh-hant/docs/chapter_introduction/what_is_dsa.md @@ -10,7 +10,7 @@ ## 資料結構定義 -資料結構(data structure)是計算機中組織和儲存資料的方式,具有以下設計目標。 +資料結構(data structure)是組織和儲存資料的方式,涵蓋資料內容、資料之間關係和資料操作方法,它具有以下設計目標。 - 空間佔用儘量少,以節省計算機記憶體。 - 資料操作儘可能快速,涵蓋資料訪問、新增、刪除、更新等。