mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 06:07:20 +08:00 
			
		
		
		
	feat: add ruby codes - chapter greedy (#1350)
This commit is contained in:
		
							
								
								
									
										50
									
								
								codes/ruby/chapter_greedy/coin_change_greedy.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								codes/ruby/chapter_greedy/coin_change_greedy.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					=begin
 | 
				
			||||||
 | 
					File: coin_change_greedy.rb
 | 
				
			||||||
 | 
					Created Time: 2024-05-07
 | 
				
			||||||
 | 
					Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
 | 
				
			||||||
 | 
					=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
 | 
				
			||||||
							
								
								
									
										51
									
								
								codes/ruby/chapter_greedy/fractional_knapsack.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								codes/ruby/chapter_greedy/fractional_knapsack.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					=begin
 | 
				
			||||||
 | 
					File: fractional_knapsack.rb
 | 
				
			||||||
 | 
					Created Time: 2024-05-07
 | 
				
			||||||
 | 
					Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
 | 
				
			||||||
 | 
					=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
 | 
				
			||||||
							
								
								
									
										37
									
								
								codes/ruby/chapter_greedy/max_capacity.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								codes/ruby/chapter_greedy/max_capacity.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					=begin
 | 
				
			||||||
 | 
					File: max_capacity.rb
 | 
				
			||||||
 | 
					Created Time: 2024-05-07
 | 
				
			||||||
 | 
					Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
 | 
				
			||||||
 | 
					=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
 | 
				
			||||||
							
								
								
									
										28
									
								
								codes/ruby/chapter_greedy/max_product_cutting.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								codes/ruby/chapter_greedy/max_product_cutting.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					=begin
 | 
				
			||||||
 | 
					File: max_product_cutting.rb
 | 
				
			||||||
 | 
					Created Time: 2024-05-07
 | 
				
			||||||
 | 
					Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
 | 
				
			||||||
 | 
					=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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user