Sync zh and zh-hant versions.
This commit is contained in:
parent
19503bab42
commit
3991ca7b30
@ -19,7 +19,7 @@ fun merge(nums: IntArray, left: Int, mid: Int, right: Int) {
|
||||
while (i <= mid && j <= right) {
|
||||
if (nums[i] <= nums[j])
|
||||
tmp[k++] = nums[i++]
|
||||
else
|
||||
else
|
||||
tmp[k++] = nums[j++]
|
||||
}
|
||||
// 将左子数组和右子数组的剩余元素复制到临时数组中
|
||||
|
@ -41,7 +41,7 @@ def merge_sort(nums: list[int], left: int, right: int):
|
||||
if left >= right:
|
||||
return # 當子陣列長度為 1 時終止遞迴
|
||||
# 劃分階段
|
||||
mid = left + (right - left) // 2 # 計算中點
|
||||
mid = (left + right) // 2 # 計算中點
|
||||
merge_sort(nums, left, mid) # 遞迴左子陣列
|
||||
merge_sort(nums, mid + 1, right) # 遞迴右子陣列
|
||||
# 合併階段
|
||||
|
61
zh-hant/codes/ruby/chapter_backtracking/n_queens.rb
Normal file
61
zh-hant/codes/ruby/chapter_backtracking/n_queens.rb
Normal file
@ -0,0 +1,61 @@
|
||||
=begin
|
||||
File: n_queens.rb
|
||||
Created Time: 2024-05-21
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:n 皇后 ###
|
||||
def backtrack(row, n, state, res, cols, diags1, diags2)
|
||||
# 當放置完所有行時,記錄解
|
||||
if row == n
|
||||
res << state.map { |row| row.dup }
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有列
|
||||
for col in 0...n
|
||||
# 計算該格子對應的主對角線和次對角線
|
||||
diag1 = row - col + n - 1
|
||||
diag2 = row + col
|
||||
# 剪枝:不允許該格子所在列、主對角線、次對角線上存在皇后
|
||||
if !cols[col] && !diags1[diag1] && !diags2[diag2]
|
||||
# 嘗試:將皇后放置在該格子
|
||||
state[row][col] = "Q"
|
||||
cols[col] = diags1[diag1] = diags2[diag2] = true
|
||||
# 放置下一行
|
||||
backtrack(row + 1, n, state, res, cols, diags1, diags2)
|
||||
# 回退:將該格子恢復為空位
|
||||
state[row][col] = "#"
|
||||
cols[col] = diags1[diag1] = diags2[diag2] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
### 求解 n 皇后 ###
|
||||
def n_queens(n)
|
||||
# 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位
|
||||
state = Array.new(n) { Array.new(n, "#") }
|
||||
cols = Array.new(n, false) # 記錄列是否有皇后
|
||||
diags1 = Array.new(2 * n - 1, false) # 記錄主對角線上是否有皇后
|
||||
diags2 = Array.new(2 * n - 1, false) # 記錄次對角線上是否有皇后
|
||||
res = []
|
||||
backtrack(0, n, state, res, cols, diags1, diags2)
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
n = 4
|
||||
res = n_queens(n)
|
||||
|
||||
puts "輸入棋盤長寬為 #{n}"
|
||||
puts "皇后放置方案共有 #{res.length} 種"
|
||||
|
||||
for state in res
|
||||
puts "--------------------"
|
||||
for row in state
|
||||
p row
|
||||
end
|
||||
end
|
||||
end
|
46
zh-hant/codes/ruby/chapter_backtracking/permutations_i.rb
Normal file
46
zh-hant/codes/ruby/chapter_backtracking/permutations_i.rb
Normal file
@ -0,0 +1,46 @@
|
||||
=begin
|
||||
File: permutations_i.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:全排列 I ###
|
||||
def backtrack(state, choices, selected, res)
|
||||
# 當狀態長度等於元素數量時,記錄解
|
||||
if state.length == choices.length
|
||||
res << state.dup
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有選擇
|
||||
choices.each_with_index do |choice, i|
|
||||
# 剪枝:不允許重複選擇元素
|
||||
unless selected[i]
|
||||
# 嘗試:做出選擇,更新狀態
|
||||
selected[i] = true
|
||||
state << choice
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, choices, selected, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
selected[i] = false
|
||||
state.pop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
### 全排列 I ###
|
||||
def permutations_i(nums)
|
||||
res = []
|
||||
backtrack([], nums, Array.new(nums.length, false), res)
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
nums = [1, 2, 3]
|
||||
|
||||
res = permutations_i(nums)
|
||||
|
||||
puts "輸入陣列 nums = #{nums}"
|
||||
puts "所有排列 res = #{res}"
|
||||
end
|
48
zh-hant/codes/ruby/chapter_backtracking/permutations_ii.rb
Normal file
48
zh-hant/codes/ruby/chapter_backtracking/permutations_ii.rb
Normal file
@ -0,0 +1,48 @@
|
||||
=begin
|
||||
File: permutations_ii.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:全排列 II ###
|
||||
def backtrack(state, choices, selected, res)
|
||||
# 當狀態長度等於元素數量時,記錄解
|
||||
if state.length == choices.length
|
||||
res << state.dup
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有選擇
|
||||
duplicated = Set.new
|
||||
choices.each_with_index do |choice, i|
|
||||
# 剪枝:不允許重複選擇元素 且 不允許重複選擇相等元素
|
||||
if !selected[i] && !duplicated.include?(choice)
|
||||
# 嘗試:做出選擇,更新狀態
|
||||
duplicated.add(choice)
|
||||
selected[i] = true
|
||||
state << choice
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, choices, selected, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
selected[i] = false
|
||||
state.pop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
### 全排列 II ###
|
||||
def permutations_ii(nums)
|
||||
res = []
|
||||
backtrack([], nums, Array.new(nums.length, false), res)
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
nums = [1, 2, 2]
|
||||
|
||||
res = permutations_ii(nums)
|
||||
|
||||
puts "輸入陣列 nums = #{nums}"
|
||||
puts "所有排列 res = #{res}"
|
||||
end
|
@ -0,0 +1,33 @@
|
||||
=begin
|
||||
File: preorder_traversal_i_compact.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
require_relative '../utils/tree_node'
|
||||
require_relative '../utils/print_util'
|
||||
|
||||
### 前序走訪:例題一 ###
|
||||
def pre_order(root)
|
||||
return unless root
|
||||
|
||||
# 記錄解
|
||||
$res << root if root.val == 7
|
||||
|
||||
pre_order(root.left)
|
||||
pre_order(root.right)
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
root = arr_to_tree([1, 7, 3, 4, 5, 6, 7])
|
||||
puts "\n初始化二元樹"
|
||||
print_tree(root)
|
||||
|
||||
# 前序走訪
|
||||
$res = []
|
||||
pre_order(root)
|
||||
|
||||
puts "\n輸出所有值為 7 的節點"
|
||||
p $res.map { |node| node.val }
|
||||
end
|
@ -0,0 +1,41 @@
|
||||
=begin
|
||||
File: preorder_traversal_ii_compact.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
require_relative '../utils/tree_node'
|
||||
require_relative '../utils/print_util'
|
||||
|
||||
### 前序走訪:例題二 ###
|
||||
def pre_order(root)
|
||||
return unless root
|
||||
|
||||
# 嘗試
|
||||
$path << root
|
||||
|
||||
# 記錄解
|
||||
$res << $path.dup if root.val == 7
|
||||
|
||||
pre_order(root.left)
|
||||
pre_order(root.right)
|
||||
|
||||
# 回退
|
||||
$path.pop
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
root = arr_to_tree([1, 7, 3, 4, 5, 6, 7])
|
||||
puts "\n初始化二元樹"
|
||||
print_tree(root)
|
||||
|
||||
# 前序走訪
|
||||
$path, $res = [], []
|
||||
pre_order(root)
|
||||
|
||||
puts "\n輸出所有根節點到節點 7 的路徑"
|
||||
for path in $res
|
||||
p path.map { |node| node.val }
|
||||
end
|
||||
end
|
@ -0,0 +1,42 @@
|
||||
=begin
|
||||
File: preorder_traversal_iii_compact.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
require_relative '../utils/tree_node'
|
||||
require_relative '../utils/print_util'
|
||||
|
||||
### 前序走訪:例題三 ###
|
||||
def pre_order(root)
|
||||
# 剪枝
|
||||
return if !root || root.val == 3
|
||||
|
||||
# 嘗試
|
||||
$path.append(root)
|
||||
|
||||
# 記錄解
|
||||
$res << $path.dup if root.val == 7
|
||||
|
||||
pre_order(root.left)
|
||||
pre_order(root.right)
|
||||
|
||||
# 回退
|
||||
$path.pop
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
root = arr_to_tree([1, 7, 3, 4, 5, 6, 7])
|
||||
puts "\n初始化二元樹"
|
||||
print_tree(root)
|
||||
|
||||
# 前序走訪
|
||||
$path, $res = [], []
|
||||
pre_order(root)
|
||||
|
||||
puts "\n輸出所有根節點到節點 7 的路徑,路徑中不包含值為 3 的節點"
|
||||
for path in $res
|
||||
p path.map { |node| node.val }
|
||||
end
|
||||
end
|
@ -0,0 +1,68 @@
|
||||
=begin
|
||||
File: preorder_traversal_iii_template.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
require_relative '../utils/tree_node'
|
||||
require_relative '../utils/print_util'
|
||||
|
||||
### 判斷當前狀態是否為解 ###
|
||||
def is_solution?(state)
|
||||
!state.empty? && state.last.val == 7
|
||||
end
|
||||
|
||||
### 記錄解 ###
|
||||
def record_solution(state, res)
|
||||
res << state.dup
|
||||
end
|
||||
|
||||
### 判斷在當前狀態下,該選擇是否合法 ###
|
||||
def is_valid?(state, choice)
|
||||
choice && choice.val != 3
|
||||
end
|
||||
|
||||
### 更新狀態 ###
|
||||
def make_choice(state, choice)
|
||||
state << choice
|
||||
end
|
||||
|
||||
### 恢復狀態 ###
|
||||
def undo_choice(state, choice)
|
||||
state.pop
|
||||
end
|
||||
|
||||
### 回溯演算法:例題三 ###
|
||||
def backtrack(state, choices, res)
|
||||
# 檢查是否為解
|
||||
record_solution(state, res) if is_solution?(state)
|
||||
|
||||
# 走訪所有選擇
|
||||
for choice in choices
|
||||
# 剪枝:檢查選擇是否合法
|
||||
if is_valid?(state, choice)
|
||||
# 嘗試:做出選擇,更新狀態
|
||||
make_choice(state, choice)
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, [choice.left, choice.right], res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
undo_choice(state, choice)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
root = arr_to_tree([1, 7, 3, 4, 5, 6, 7])
|
||||
puts "\n初始化二元樹"
|
||||
print_tree(root)
|
||||
|
||||
# 回溯演算法
|
||||
res = []
|
||||
backtrack([], [root], res)
|
||||
|
||||
puts "\n輸出所有根節點到節點 7 的路徑,要求路徑中不包含值為 3 的節點"
|
||||
for path in res
|
||||
p path.map { |node| node.val }
|
||||
end
|
||||
end
|
47
zh-hant/codes/ruby/chapter_backtracking/subset_sum_i.rb
Normal file
47
zh-hant/codes/ruby/chapter_backtracking/subset_sum_i.rb
Normal file
@ -0,0 +1,47 @@
|
||||
=begin
|
||||
File: subset_sum_i.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:子集和 I ###
|
||||
def backtrack(state, target, choices, start, res)
|
||||
# 子集和等於 target 時,記錄解
|
||||
if target.zero?
|
||||
res << state.dup
|
||||
return
|
||||
end
|
||||
# 走訪所有選擇
|
||||
# 剪枝二:從 start 開始走訪,避免生成重複子集
|
||||
for i in start...choices.length
|
||||
# 剪枝一:若子集和超過 target ,則直接結束迴圈
|
||||
# 這是因為陣列已排序,後邊元素更大,子集和一定超過 target
|
||||
break if target - choices[i] < 0
|
||||
# 嘗試:做出選擇,更新 target, start
|
||||
state << choices[i]
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, target - choices[i], choices, i, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
state.pop
|
||||
end
|
||||
end
|
||||
|
||||
### 求解子集和 I ###
|
||||
def subset_sum_i(nums, target)
|
||||
state = [] # 狀態(子集)
|
||||
nums.sort! # 對 nums 進行排序
|
||||
start = 0 # 走訪起始點
|
||||
res = [] # 結果串列(子集串列)
|
||||
backtrack(state, target, nums, start, res)
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
nums = [3, 4, 5]
|
||||
target = 9
|
||||
res = subset_sum_i(nums, target)
|
||||
|
||||
puts "輸入陣列 = #{nums}, target = #{target}"
|
||||
puts "所有和等於 #{target} 的子集 res = #{res}"
|
||||
end
|
@ -0,0 +1,46 @@
|
||||
=begin
|
||||
File: subset_sum_i_naive.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:子集和 I ###
|
||||
def backtrack(state, target, total, choices, res)
|
||||
# 子集和等於 target 時,記錄解
|
||||
if total == target
|
||||
res << state.dup
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有選擇
|
||||
for i in 0...choices.length
|
||||
# 剪枝:若子集和超過 target ,則跳過該選擇
|
||||
next if total + choices[i] > target
|
||||
# 嘗試:做出選擇,更新元素和 total
|
||||
state << choices[i]
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, target, total + choices[i], choices, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
state.pop
|
||||
end
|
||||
end
|
||||
|
||||
### 求解子集和 I(包含重複子集)###
|
||||
def subset_sum_i_naive(nums, target)
|
||||
state = [] # 狀態(子集)
|
||||
total = 0 # 子集和
|
||||
res = [] # 結果串列(子集串列)
|
||||
backtrack(state, target, total, nums, res)
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
nums = [3, 4, 5]
|
||||
target = 9
|
||||
res = subset_sum_i_naive(nums, target)
|
||||
|
||||
puts "輸入陣列 nums = #{nums}, target = #{target}"
|
||||
puts "所有和等於 #{target} 的子集 res = #{res}"
|
||||
puts "請注意,該方法輸出的結果包含重複集合"
|
||||
end
|
51
zh-hant/codes/ruby/chapter_backtracking/subset_sum_ii.rb
Normal file
51
zh-hant/codes/ruby/chapter_backtracking/subset_sum_ii.rb
Normal file
@ -0,0 +1,51 @@
|
||||
=begin
|
||||
File: subset_sum_ii.rb
|
||||
Created Time: 2024-05-22
|
||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||
=end
|
||||
|
||||
### 回溯演算法:子集和 II ###
|
||||
def backtrack(state, target, choices, start, res)
|
||||
# 子集和等於 target 時,記錄解
|
||||
if target.zero?
|
||||
res << state.dup
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有選擇
|
||||
# 剪枝二:從 start 開始走訪,避免生成重複子集
|
||||
# 剪枝三:從 start 開始走訪,避免重複選擇同一元素
|
||||
for i in start...choices.length
|
||||
# 剪枝一:若子集和超過 target ,則直接結束迴圈
|
||||
# 這是因為陣列已排序,後邊元素更大,子集和一定超過 target
|
||||
break if target - choices[i] < 0
|
||||
# 剪枝四:如果該元素與左邊元素相等,說明該搜尋分支重複,直接跳過
|
||||
next if i > start && choices[i] == choices[i - 1]
|
||||
# 嘗試:做出選擇,更新 target, start
|
||||
state << choices[i]
|
||||
# 進行下一輪選擇
|
||||
backtrack(state, target - choices[i], choices, i + 1, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
state.pop
|
||||
end
|
||||
end
|
||||
|
||||
### 求解子集和 II ###
|
||||
def subset_sum_ii(nums, target)
|
||||
state = [] # 狀態(子集)
|
||||
nums.sort! # 對 nums 進行排序
|
||||
start = 0 # 走訪起始點
|
||||
res = [] # 結果串列(子集串列)
|
||||
backtrack(state, target, nums, start, res)
|
||||
res
|
||||
end
|
||||
|
||||
### Driver Code ###
|
||||
if __FILE__ == $0
|
||||
nums = [4, 4, 5]
|
||||
target = 9
|
||||
res = subset_sum_ii(nums, target)
|
||||
|
||||
puts "輸入陣列 nums = #{nums}, target = #{target}"
|
||||
puts "所有和等於 #{target} 的子集 res = #{res}"
|
||||
end
|
@ -10,7 +10,7 @@ fn dfs(nums: &[i32], target: i32, i: i32, j: i32) -> i32 {
|
||||
if i > j {
|
||||
return -1;
|
||||
}
|
||||
let m: i32 = (i + j) / 2;
|
||||
let m: i32 = i + (j - i) / 2;
|
||||
if nums[m as usize] < target {
|
||||
// 遞迴子問題 f(m+1, j)
|
||||
return dfs(nums, target, m + 1, j);
|
||||
|
@ -35,9 +35,7 @@ fn counting_sort_digit(nums: &mut [i32], exp: i32) {
|
||||
counter[d] -= 1; // 將 d 的數量減 1
|
||||
}
|
||||
// 使用結果覆蓋原陣列 nums
|
||||
for i in 0..n {
|
||||
nums[i] = res[i];
|
||||
}
|
||||
nums.copy_from_slice(&res);
|
||||
}
|
||||
|
||||
/* 基數排序 */
|
||||
|
@ -48,7 +48,7 @@ fn mergeSort(nums: []i32, left: usize, right: usize) !void {
|
||||
// 終止條件
|
||||
if (left >= right) return; // 當子陣列長度為 1 時終止遞迴
|
||||
// 劃分階段
|
||||
var mid = left + (right - left) / 2; // 計算中點
|
||||
var mid = left + (right - left) / 2; // 計算中點
|
||||
try mergeSort(nums, left, mid); // 遞迴左子陣列
|
||||
try mergeSort(nums, mid + 1, right); // 遞迴右子陣列
|
||||
// 合併階段
|
||||
|
@ -406,7 +406,27 @@
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title=""
|
||||
### 回溯演算法框架 ###
|
||||
def backtrack(state, choices, res)
|
||||
# 判斷是否為解
|
||||
if is_solution?(state)
|
||||
# 記錄解
|
||||
record_solution(state, res)
|
||||
return
|
||||
end
|
||||
|
||||
# 走訪所有選擇
|
||||
for choice in choices
|
||||
# 剪枝:判斷選擇是否合法
|
||||
if is_valid?(state, choice)
|
||||
# 嘗試:做出選擇,更新狀態
|
||||
make_choice(state, choice)
|
||||
backtrack(state, choices, res)
|
||||
# 回退:撤銷選擇,恢復到之前的狀態
|
||||
undo_choice(state, choice)
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
Loading…
Reference in New Issue
Block a user