feat(go/greedy): add greedy in go code (#648)
parent
41db3701ab
commit
10e5e7499b
@ -0,0 +1,27 @@
|
|||||||
|
// File: coin_change_greedy.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
/* 零钱兑换:贪心 */
|
||||||
|
func coinChangeGreedy(coins []int, amt int) int {
|
||||||
|
// 假设 coins 列表有序
|
||||||
|
i := len(coins) - 1
|
||||||
|
count := 0
|
||||||
|
// 循环进行贪心选择,直到无剩余金额
|
||||||
|
for amt > 0 {
|
||||||
|
// 找到小于且最接近剩余金额的硬币
|
||||||
|
for coins[i] > amt {
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
// 选择 coins[i]
|
||||||
|
amt -= coins[i]
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
// 若未找到可行方案,则返回 -1
|
||||||
|
if amt != 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// File: coin_change_greedy_test.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCoinChangeGreedy(t *testing.T) {
|
||||||
|
// 贪心:能够保证找到全局最优解
|
||||||
|
coins := []int{1, 5, 10, 20, 50, 100}
|
||||||
|
amt := 186
|
||||||
|
res := coinChangeGreedy(coins, amt)
|
||||||
|
fmt.Printf("coins = %v, amt = %d\n", coins, amt)
|
||||||
|
fmt.Printf("凑到 %d 所需的最少硬币数量为 %d\n", amt, res)
|
||||||
|
|
||||||
|
// 贪心:无法保证找到全局最优解
|
||||||
|
coins = []int{1, 20, 50}
|
||||||
|
amt = 60
|
||||||
|
res = coinChangeGreedy(coins, amt)
|
||||||
|
fmt.Printf("coins = %v, amt = %d\n", coins, amt)
|
||||||
|
fmt.Printf("凑到 %d 所需的最少硬币数量为 %d\n", amt, res)
|
||||||
|
fmt.Println("实际上需要的最少数量为 3 ,即 20 + 20 + 20")
|
||||||
|
|
||||||
|
// 贪心:无法保证找到全局最优解
|
||||||
|
coins = []int{1, 49, 50}
|
||||||
|
amt = 98
|
||||||
|
res = coinChangeGreedy(coins, amt)
|
||||||
|
fmt.Printf("coins = %v, amt = %d\n", coins, amt)
|
||||||
|
fmt.Printf("凑到 %d 所需的最少硬币数量为 %d\n", amt, res)
|
||||||
|
fmt.Println("实际上需要的最少数量为 2 ,即 49 + 49")
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
// File: fractional_knapsack.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
/* 物品 */
|
||||||
|
type Item struct {
|
||||||
|
w int // 物品重量
|
||||||
|
v int // 物品价值
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分数背包:贪心 */
|
||||||
|
func fractionalKnapsack(wgt []int, val []int, cap int) float64 {
|
||||||
|
// 创建物品列表,包含两个属性:重量、价值
|
||||||
|
items := make([]Item, len(wgt))
|
||||||
|
for i := 0; i < len(wgt); i++ {
|
||||||
|
items[i] = Item{wgt[i], val[i]}
|
||||||
|
}
|
||||||
|
// 按照单位价值 item.v / item.w 从高到低进行排序
|
||||||
|
sort.Slice(items, func(i, j int) bool {
|
||||||
|
return float64(items[i].v)/float64(items[i].w) > float64(items[j].v)/float64(items[j].w)
|
||||||
|
})
|
||||||
|
// 循环贪心选择
|
||||||
|
res := 0.0
|
||||||
|
for _, item := range items {
|
||||||
|
if item.w <= cap {
|
||||||
|
// 若剩余容量充足,则将当前物品整个装进背包
|
||||||
|
res += float64(item.v)
|
||||||
|
cap -= item.w
|
||||||
|
} else {
|
||||||
|
// 若剩余容量不足,则将当前物品的一部分装进背包
|
||||||
|
res += float64(item.v) / float64(item.w) * float64(cap)
|
||||||
|
// 已无剩余容量,因此跳出循环
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
// File: fractional_knapsack_test.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFractionalKnapsack(t *testing.T) {
|
||||||
|
wgt := []int{10, 20, 30, 40, 50}
|
||||||
|
val := []int{50, 120, 150, 210, 240}
|
||||||
|
capacity := 50
|
||||||
|
|
||||||
|
// 贪心算法
|
||||||
|
res := fractionalKnapsack(wgt, val, capacity)
|
||||||
|
fmt.Println("不超过背包容量的最大物品价值为", res)
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
// File: max_capacity.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
/* 最大容量:贪心 */
|
||||||
|
func maxCapacity(ht []int) int {
|
||||||
|
// 初始化 i, j 分列数组两端
|
||||||
|
i, j := 0, len(ht)-1
|
||||||
|
// 初始最大容量为 0
|
||||||
|
res := 0
|
||||||
|
// 循环贪心选择,直至两板相遇
|
||||||
|
for i < j {
|
||||||
|
// 更新最大容量
|
||||||
|
capacity := int(math.Min(float64(ht[i]), float64(ht[j]))) * (j - i)
|
||||||
|
res = int(math.Max(float64(res), float64(capacity)))
|
||||||
|
// 向内移动短板
|
||||||
|
if ht[i] < ht[j] {
|
||||||
|
i++
|
||||||
|
} else {
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
// File: max_capacity_test.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMaxCapacity(t *testing.T) {
|
||||||
|
ht := []int{3, 8, 5, 2, 7, 7, 3, 4}
|
||||||
|
|
||||||
|
// 贪心算法
|
||||||
|
res := maxCapacity(ht)
|
||||||
|
fmt.Println("最大容量为", res)
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
// File: max_product_cutting_test.go
|
||||||
|
// Created Time: 2023-07-23
|
||||||
|
// Author: Reanon (793584285@qq.com)
|
||||||
|
|
||||||
|
package chapter_greedy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMaxProductCutting(t *testing.T) {
|
||||||
|
n := 58
|
||||||
|
// 贪心算法
|
||||||
|
res := maxProductCutting(n)
|
||||||
|
fmt.Println("最大切分乘积为", res)
|
||||||
|
}
|
Loading…
Reference in new issue