-
Notifications
You must be signed in to change notification settings - Fork 12.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Ruby code - chapter "Backtracking" (#1373)
* [feat] add ruby code - chapter backtracking * feat: add ruby code block - chapter backtracking
- Loading branch information
1 parent
21be3fd
commit aa81894
Showing
11 changed files
with
503 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
33 changes: 33 additions & 0 deletions
33
codes/ruby/chapter_backtracking/preorder_traversal_i_compact.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
41 changes: 41 additions & 0 deletions
41
codes/ruby/chapter_backtracking/preorder_traversal_ii_compact.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
42 changes: 42 additions & 0 deletions
42
codes/ruby/chapter_backtracking/preorder_traversal_iii_compact.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
68 changes: 68 additions & 0 deletions
68
codes/ruby/chapter_backtracking/preorder_traversal_iii_template.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.