-
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 "Searching" (#1262)
* create RUBY searching files & finish two_sum.rb * finish linear_search.rb * finish hashing_search.rb * finish binary_search.rb * finish binary_search_insertion.rb * finish binary_search_edge.rb * fix: change 'or' to '||' * fix: Adjust the code style(ruby searching) * fix: repair file name * fix: Adjust the output format * fix: fix 0...nums.length & delete useless require & change into __FILE__==0 block
- Loading branch information
1 parent
aca8502
commit 9233767
Showing
6 changed files
with
315 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,63 @@ | ||
=begin | ||
File: binary_search.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
### 二分查找(双闭区间) ### | ||
def binary_search(nums, target) | ||
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 | ||
i, j = 0, nums.length - 1 | ||
|
||
# 循环,当搜索区间为空时跳出(当 i > j 时为空) | ||
while i <= j | ||
# 理论上 Ruby 的数字可以无限大(取决于内存大小),无须考虑大数越界问题 | ||
m = (i + j) / 2 # 计算中点索引 m | ||
|
||
if nums[m] < target | ||
i = m + 1 # 此情况说明 target 在区间 [m+1, j] 中 | ||
elsif nums[m] > target | ||
j = m - 1 # 此情况说明 target 在区间 [i, m-1] 中 | ||
else | ||
return m # 找到目标元素,返回其索引 | ||
end | ||
end | ||
|
||
-1 # 未找到目标元素,返回 -1 | ||
end | ||
|
||
### 二分查找(左闭右开区间) ### | ||
def binary_search_lcro(nums, target) | ||
# 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 | ||
i, j = 0, nums.length | ||
|
||
# 循环,当搜索区间为空时跳出(当 i = j 时为空) | ||
while i < j | ||
# 计算中点索引 m | ||
m = (i + j) / 2 | ||
|
||
if nums[m] < target | ||
i = m + 1 # 此情况说明 target 在区间 [m+1, j) 中 | ||
elsif nums[m] > target | ||
j = m - 1 # 此情况说明 target 在区间 [i, m) 中 | ||
else | ||
return m # 找到目标元素,返回其索引 | ||
end | ||
end | ||
|
||
-1 # 未找到目标元素,返回 -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}" | ||
|
||
# 二分查找(左闭右开区间) | ||
index = binary_search_lcro(nums, target) | ||
puts "目标元素 6 的索引 = #{index}" | ||
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: binary_search_edge.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
require_relative './binary_search_insertion' | ||
|
||
### 二分查找最左一个 target ### | ||
def binary_search_left_edge(nums, target) | ||
# 等价于查找 target 的插入点 | ||
i = binary_search_insertion(nums, target) | ||
|
||
# 未找到 target ,返回 -1 | ||
return -1 if i == nums.length || nums[i] != target | ||
|
||
i # 找到 target ,返回索引 i | ||
end | ||
|
||
### 二分查找最右一个 target ### | ||
def binary_search_right_edge(nums, target) | ||
# 转化为查找最左一个 target + 1 | ||
i = binary_search_insertion(nums, target + 1) | ||
|
||
# j 指向最右一个 target ,i 指向首个大于 target 的元素 | ||
j = i - 1 | ||
|
||
# 未找到 target ,返回 -1 | ||
return -1 if j == -1 || nums[j] != target | ||
|
||
j # 找到 target ,返回索引 j | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
# 包含重复元素的数组 | ||
nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15] | ||
puts "\n数组 nums = #{nums}" | ||
|
||
# 二分查找左边界和右边界 | ||
for target in [6, 7] | ||
index = binary_search_left_edge(nums, target) | ||
puts "最左一个元素 #{target} 的索引为 #{index}" | ||
index = binary_search_right_edge(nums, target) | ||
puts "最右一个元素 #{target} 的索引为 #{index}" | ||
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,68 @@ | ||
=begin | ||
File: binary_search_insertion.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
### 二分查找插入点(无重复元素) ### | ||
def binary_search_insertion_simple(nums, target) | ||
# 初始化双闭区间 [0, n-1] | ||
i, j = 0, nums.length - 1 | ||
|
||
while i <= j | ||
# 计算中点索引 m | ||
m = (i + j) / 2 | ||
|
||
if nums[m] < target | ||
i = m + 1 # target 在区间 [m+1, j] 中 | ||
elsif nums[m] > target | ||
j = m - 1 # target 在区间 [i, m-1] 中 | ||
else | ||
return m # 找到 target ,返回插入点 m | ||
end | ||
end | ||
|
||
i # 未找到 target ,返回插入点 i | ||
end | ||
|
||
### 二分查找插入点(存在重复元素) ### | ||
def binary_search_insertion(nums, target) | ||
# 初始化双闭区间 [0, n-1] | ||
i, j = 0, nums.length - 1 | ||
|
||
while i <= j | ||
# 计算中点索引 m | ||
m = (i + j) / 2 | ||
|
||
if nums[m] < target | ||
i = m + 1 # target 在区间 [m+1, j] 中 | ||
elsif nums[m] > target | ||
j = m - 1 # target 在区间 [i, m-1] 中 | ||
else | ||
j = m - 1 # 首个小于 target 的元素在区间 [i, m-1] 中 | ||
end | ||
end | ||
|
||
i # 返回插入点 i | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
# 无重复元素的数组 | ||
nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35] | ||
puts "\n数组 nums = #{nums}" | ||
# 二分查找插入点 | ||
for target in [6, 9] | ||
index = binary_search_insertion_simple(nums, target) | ||
puts "元素 #{target} 的插入点的索引为 #{index}" | ||
end | ||
|
||
# 包含重复元素的数组 | ||
nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15] | ||
puts "\n数组 nums = #{nums}" | ||
# 二分查找插入点 | ||
for target in [2, 6, 20] | ||
index = binary_search_insertion(nums, target) | ||
puts "元素 #{target} 的插入点的索引为 #{index}" | ||
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: hashing_search.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
require_relative '../utils/list_node' | ||
|
||
### 哈希查找(数组) ### | ||
def hashing_search_array(hmap, target) | ||
# 哈希表的 key: 目标元素,value: 索引 | ||
# 若哈希表中无此 key ,返回 -1 | ||
hmap[target] || -1 | ||
end | ||
|
||
### 哈希查找(链表) ### | ||
def hashing_search_linkedlist(hmap, target) | ||
# 哈希表的 key: 目标元素,value: 节点对象 | ||
# 若哈希表中无此 key ,返回 None | ||
hmap[target] || nil | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
target = 3 | ||
|
||
# 哈希查找(数组) | ||
nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8] | ||
# 初始化哈希表 | ||
map0 = {} | ||
for i in 0...nums.length | ||
map0[nums[i]] = i # key: 元素,value: 索引 | ||
end | ||
index = hashing_search_array(map0, target) | ||
puts "目标元素 3 的索引 = #{index}" | ||
|
||
# 哈希查找(链表) | ||
head = arr_to_linked_list(nums) | ||
# 初始化哈希表 | ||
map1 = {} | ||
while head | ||
map1[head.val] = head | ||
head = head.next | ||
end | ||
node = hashing_search_linkedlist(map1, target) | ||
puts "目标节点值 3 的对应节点对象为 #{node}" | ||
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,44 @@ | ||
=begin | ||
File: linear_search.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
require_relative '../utils/list_node' | ||
|
||
### 线性查找(数组) ### | ||
def linear_search_array(nums, target) | ||
# 遍历数组 | ||
for i in 0...nums.length | ||
return i if nums[i] == target # 找到目标元素,返回其索引 | ||
end | ||
|
||
-1 # 未找到目标元素,返回 -1 | ||
end | ||
|
||
### 线性查找(链表) ### | ||
def linear_search_linkedlist(head, target) | ||
# 遍历链表 | ||
while head | ||
return head if head.val == target # 找到目标节点,返回之 | ||
|
||
head = head.next | ||
end | ||
|
||
nil # 未找到目标节点,返回 None | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
target = 3 | ||
|
||
# 在数组中执行线性查找 | ||
nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8] | ||
index = linear_search_array(nums, target) | ||
puts "目标元素 3 的索引 = #{index}" | ||
|
||
# 在链表中执行线性查找 | ||
head = arr_to_linked_list(nums) | ||
node = linear_search_linkedlist(head, target) | ||
puts "目标节点值 3 的对应节点对象为 #{node}" | ||
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: two_sum.rb | ||
Created Time: 2024-04-09 | ||
Author: Blue Bean ([email protected]) | ||
=end | ||
|
||
### 方法一:暴力枚举 ### | ||
def two_sum_brute_force(nums, target) | ||
# 两层循环,时间复杂度为 O(n^2) | ||
for i in 0...(nums.length - 1) | ||
for j in (i + 1)...nums.length | ||
return [i, j] if nums[i] + nums[j] == target | ||
end | ||
end | ||
|
||
[] | ||
end | ||
|
||
### 方法二:辅助哈希表 ### | ||
def two_sum_hash_table(nums, target) | ||
# 辅助哈希表,空间复杂度为 O(n) | ||
dic = {} | ||
# 单层循环,时间复杂度为 O(n) | ||
for i in 0...nums.length | ||
return [dic[target - nums[i]], i] if dic.has_key?(target - nums[i]) | ||
|
||
dic[nums[i]] = i | ||
end | ||
|
||
[] | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
# ======= Test Case ======= | ||
nums = [2, 7, 11, 15] | ||
target = 13 | ||
|
||
# ====== Driver Code ====== | ||
# 方法一 | ||
res = two_sum_brute_force(nums, target) | ||
puts "方法一 res = #{res}" | ||
# 方法二 | ||
res = two_sum_hash_table(nums, target) | ||
puts "方法二 res = #{res}" | ||
end |