-
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 codes - chapter greedy (#1350)
- Loading branch information
1 parent
56a165b
commit 1f606d6
Showing
4 changed files
with
166 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,50 @@ | ||
=begin | ||
File: coin_change_greedy.rb | ||
Created Time: 2024-05-07 | ||
Author: Xuan Khoa Tu Nguyen ([email protected]) | ||
=end | ||
|
||
### 零钱兑换:贪心 ### | ||
def coin_change_greedy(coins, amt) | ||
# 假设 coins 列表有序 | ||
i = coins.length - 1 | ||
count = 0 | ||
# 循环进行贪心选择,直到无剩余金额 | ||
while amt > 0 | ||
# 找到小于且最接近剩余金额的硬币 | ||
while i > 0 && coins[i] > amt | ||
i -= 1 | ||
end | ||
# 选择 coins[i] | ||
amt -= coins[i] | ||
count += 1 | ||
end | ||
# 若未找到可行方案, 则返回 -1 | ||
amt == 0 ? count : -1 | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
# 贪心:能够保证找到全局最优解 | ||
coins = [1, 5, 10, 20, 50, 100] | ||
amt = 186 | ||
res = coin_change_greedy(coins, amt) | ||
puts "\ncoins = #{coins}, amt = #{amt}" | ||
puts "凑到 #{amt} 所需的最少硬币数量为 #{res}" | ||
|
||
# 贪心:无法保证找到全局最优解 | ||
coins = [1, 20, 50] | ||
amt = 60 | ||
res = coin_change_greedy(coins, amt) | ||
puts "\ncoins = #{coins}, amt = #{amt}" | ||
puts "凑到 #{amt} 所需的最少硬币数量为 #{res}" | ||
puts "实际上需要的最少数量为 3 , 即 20 + 20 + 20" | ||
|
||
# 贪心:无法保证找到全局最优解 | ||
coins = [1, 49, 50] | ||
amt = 98 | ||
res = coin_change_greedy(coins, amt) | ||
puts "\ncoins = #{coins}, amt = #{amt}" | ||
puts "凑到 #{amt} 所需的最少硬币数量为 #{res}" | ||
puts "实际上需要的最少数量为 2 , 即 49 + 49" | ||
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,51 @@ | ||
=begin | ||
File: fractional_knapsack.rb | ||
Created Time: 2024-05-07 | ||
Author: Xuan Khoa Tu Nguyen ([email protected]) | ||
=end | ||
|
||
### 物品 ### | ||
class Item | ||
attr_accessor :w # 物品重量 | ||
attr_accessor :v # 物品价值 | ||
|
||
def initialize(w, v) | ||
@w = w | ||
@v = v | ||
end | ||
end | ||
|
||
### 分数背包:贪心 ### | ||
def fractional_knapsack(wgt, val, cap) | ||
# 创建物品列表,包含两个属性:重量,价值 | ||
items = wgt.each_with_index.map { |w, i| Item.new(w, val[i]) } | ||
# 按照单位价值 item.v / item.w 从高到低进行排序 | ||
items.sort! { |a, b| (b.v.to_f / b.w) <=> (a.v.to_f / a.w) } | ||
# 循环贪心选择 | ||
res = 0 | ||
for item in items | ||
if item.w <= cap | ||
# 若剩余容量充足,则将当前物品整个装进背包 | ||
res += item.v | ||
cap -= item.w | ||
else | ||
# 若剩余容量不足,则将当前物品的一部分装进背包 | ||
res += (item.v.to_f / item.w) * cap | ||
# 已无剩余容量,因此跳出循环 | ||
break | ||
end | ||
end | ||
res | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
wgt = [10, 20, 30, 40, 50] | ||
val = [50, 120, 150, 210, 240] | ||
cap = 50 | ||
n = wgt.length | ||
|
||
# 贪心算法 | ||
res = fractional_knapsack(wgt, val, cap) | ||
puts "不超过背包容量的最大物品价值为 #{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,37 @@ | ||
=begin | ||
File: max_capacity.rb | ||
Created Time: 2024-05-07 | ||
Author: Xuan Khoa Tu Nguyen ([email protected]) | ||
=end | ||
|
||
### 最大容量:贪心 ### | ||
def max_capacity(ht) | ||
# 初始化 i, j,使其分列数组两端 | ||
i, j = 0, ht.length - 1 | ||
# 初始最大容量为 0 | ||
res = 0 | ||
|
||
# 循环贪心选择,直至两板相遇 | ||
while i < j | ||
# 更新最大容量 | ||
cap = [ht[i], ht[j]].min * (j - i) | ||
res = [res, cap].max | ||
# 向内移动短板 | ||
if ht[i] < ht[j] | ||
i += 1 | ||
else | ||
j -= 1 | ||
end | ||
end | ||
|
||
res | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
ht = [3, 8, 5, 2, 7, 7, 3, 4] | ||
|
||
# 贪心算法 | ||
res = max_capacity(ht) | ||
puts "最大容量为 #{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,28 @@ | ||
=begin | ||
File: max_product_cutting.rb | ||
Created Time: 2024-05-07 | ||
Author: Xuan Khoa Tu Nguyen ([email protected]) | ||
=end | ||
|
||
### 最大切分乘积:贪心 ### | ||
def max_product_cutting(n) | ||
# 当 n <= 3 时,必须切分出一个 1 | ||
return 1 * (n - 1) if n <= 3 | ||
# 贪心地切分出 3 ,a 为 3 的个数,b 为余数 | ||
a, b = n / 3, n % 3 | ||
# 当余数为 1 时,将一对 1 * 3 转化为 2 * 2 | ||
return (3.pow(a - 1) * 2 * 2).to_i if b == 1 | ||
# 当余数为 2 时,不做处理 | ||
return (3.pow(a) * 2).to_i if b == 2 | ||
# 当余数为 0 时,不做处理 | ||
3.pow(a).to_i | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
n = 58 | ||
|
||
# 贪心算法 | ||
res = max_product_cutting(n) | ||
puts "最大切分乘积为 #{res}" | ||
end |