mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-10-31 10:26:48 +08:00 
			
		
		
		
	Sync zh and zh-hant versions. (#1523)
This commit is contained in:
		| @ -9,26 +9,19 @@ | ||||
| /* 快速排序類別 */ | ||||
| class QuickSort { | ||||
|   private: | ||||
|     /* 元素交換 */ | ||||
|     static void swap(vector<int> &nums, int i, int j) { | ||||
|         int tmp = nums[i]; | ||||
|         nums[i] = nums[j]; | ||||
|         nums[j] = tmp; | ||||
|     } | ||||
|  | ||||
|     /* 哨兵劃分 */ | ||||
|     static int partition(vector<int> &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<int> &nums, int i, int j) { | ||||
|         int tmp = nums[i]; | ||||
|         nums[i] = nums[j]; | ||||
|         nums[j] = tmp; | ||||
|     } | ||||
|  | ||||
|     /* 選取三個候選元素的中位數 */ | ||||
|     static int medianThree(vector<int> &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<int> &nums, int i, int j) { | ||||
|         int tmp = nums[i]; | ||||
|         nums[i] = nums[j]; | ||||
|         nums[j] = tmp; | ||||
|     } | ||||
|  | ||||
|     /* 哨兵劃分 */ | ||||
|     static int partition(vector<int> &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: | ||||
|  | ||||
| @ -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]; | ||||
|         } | ||||
|  | ||||
| @ -16,11 +16,7 @@ fn backtrack( | ||||
| ) { | ||||
|     // 當放置完所有行時,記錄解 | ||||
|     if row == n { | ||||
|         let mut copy_state: Vec<Vec<String>> = 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<Vec<Vec<String>>> { | ||||
|     // 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位 | ||||
|     let mut state: Vec<Vec<String>> = Vec::new(); | ||||
|     for _ in 0..n { | ||||
|         let mut row: Vec<String> = Vec::new(); | ||||
|         for _ in 0..n { | ||||
|             row.push("#".into()); | ||||
|         } | ||||
|         state.push(row); | ||||
|     } | ||||
|     let mut state: Vec<Vec<String>> = 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]; // 記錄次對角線上是否有皇后 | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  | ||||
| /* 回溯演算法:子集和 I */ | ||||
| fn backtrack( | ||||
|     mut state: Vec<i32>, | ||||
|     state: &mut Vec<i32>, | ||||
|     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<Vec<i32>> { | ||||
|     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 | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  | ||||
| /* 回溯演算法:子集和 I */ | ||||
| fn backtrack( | ||||
|     mut state: Vec<i32>, | ||||
|     state: &mut Vec<i32>, | ||||
|     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<Vec<i32>> { | ||||
|     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 | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  | ||||
| /* 回溯演算法:子集和 II */ | ||||
| fn backtrack( | ||||
|     mut state: Vec<i32>, | ||||
|     state: &mut Vec<i32>, | ||||
|     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<Vec<i32>> { | ||||
|     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 | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -29,7 +29,7 @@ impl<T> ListNode<T> { | ||||
|         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<T> ListNode<T> { | ||||
|         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 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -72,23 +72,21 @@ pub fn vec_to_tree(arr: Vec<Option<i32>>) -> Option<Rc<RefCell<TreeNode>>> { | ||||
| } | ||||
|  | ||||
| /* 將二元樹序列化為串列:遞迴 */ | ||||
| fn tree_to_vec_dfs(root: Option<Rc<RefCell<TreeNode>>>, i: usize, res: &mut Vec<Option<i32>>) { | ||||
|     if root.is_none() { | ||||
|         return; | ||||
| fn tree_to_vec_dfs(root: Option<&Rc<RefCell<TreeNode>>>, i: usize, res: &mut Vec<Option<i32>>) { | ||||
|     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<Rc<RefCell<TreeNode>>>) -> Vec<Option<i32>> { | ||||
|     let mut res = vec![]; | ||||
|     tree_to_vec_dfs(root, 0, &mut res); | ||||
|     tree_to_vec_dfs(root.as_ref(), 0, &mut res); | ||||
|     res | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Yudong Jin
					Yudong Jin