Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Ruby code - chapter "Divide and Conquer" #1361

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions codes/ruby/chapter_divide_and_conquer/binary_search_recur.rb
Original file line number Diff line number Diff line change
@@ -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
46 changes: 46 additions & 0 deletions codes/ruby/chapter_divide_and_conquer/build_tree.rb
Original file line number Diff line number Diff line change
@@ -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
55 changes: 55 additions & 0 deletions codes/ruby/chapter_divide_and_conquer/hanota.rb
Original file line number Diff line number Diff line change
@@ -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