From 10e5e7499bf58770d1472538d72f7137fad4f212 Mon Sep 17 00:00:00 2001 From: Reanon <793584285@qq.com> Date: Mon, 24 Jul 2023 03:06:47 +0800 Subject: [PATCH] feat(go/greedy): add greedy in go code (#648) --- codes/go/chapter_greedy/coin_change_greedy.go | 27 ++++++++++++ .../chapter_greedy/coin_change_greedy_test.go | 35 ++++++++++++++++ .../go/chapter_greedy/fractional_knapsack.go | 41 +++++++++++++++++++ .../fractional_knapsack_test.go | 20 +++++++++ codes/go/chapter_greedy/max_capacity.go | 28 +++++++++++++ codes/go/chapter_greedy/max_capacity_test.go | 18 ++++++++ .../go/chapter_greedy/max_product_cutting.go | 28 +++++++++++++ .../max_product_cutting_test.go | 17 ++++++++ 8 files changed, 214 insertions(+) create mode 100644 codes/go/chapter_greedy/coin_change_greedy.go create mode 100644 codes/go/chapter_greedy/coin_change_greedy_test.go create mode 100644 codes/go/chapter_greedy/fractional_knapsack.go create mode 100644 codes/go/chapter_greedy/fractional_knapsack_test.go create mode 100644 codes/go/chapter_greedy/max_capacity.go create mode 100644 codes/go/chapter_greedy/max_capacity_test.go create mode 100644 codes/go/chapter_greedy/max_product_cutting.go create mode 100644 codes/go/chapter_greedy/max_product_cutting_test.go diff --git a/codes/go/chapter_greedy/coin_change_greedy.go b/codes/go/chapter_greedy/coin_change_greedy.go new file mode 100644 index 000000000..a5e6091e2 --- /dev/null +++ b/codes/go/chapter_greedy/coin_change_greedy.go @@ -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 +} diff --git a/codes/go/chapter_greedy/coin_change_greedy_test.go b/codes/go/chapter_greedy/coin_change_greedy_test.go new file mode 100644 index 000000000..0c0bac32a --- /dev/null +++ b/codes/go/chapter_greedy/coin_change_greedy_test.go @@ -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") +} diff --git a/codes/go/chapter_greedy/fractional_knapsack.go b/codes/go/chapter_greedy/fractional_knapsack.go new file mode 100644 index 000000000..04ffb0f8f --- /dev/null +++ b/codes/go/chapter_greedy/fractional_knapsack.go @@ -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 +} diff --git a/codes/go/chapter_greedy/fractional_knapsack_test.go b/codes/go/chapter_greedy/fractional_knapsack_test.go new file mode 100644 index 000000000..bb3b0f76b --- /dev/null +++ b/codes/go/chapter_greedy/fractional_knapsack_test.go @@ -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) +} diff --git a/codes/go/chapter_greedy/max_capacity.go b/codes/go/chapter_greedy/max_capacity.go new file mode 100644 index 000000000..6e4254b3c --- /dev/null +++ b/codes/go/chapter_greedy/max_capacity.go @@ -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 +} diff --git a/codes/go/chapter_greedy/max_capacity_test.go b/codes/go/chapter_greedy/max_capacity_test.go new file mode 100644 index 000000000..9b14aff4a --- /dev/null +++ b/codes/go/chapter_greedy/max_capacity_test.go @@ -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) +} diff --git a/codes/go/chapter_greedy/max_product_cutting.go b/codes/go/chapter_greedy/max_product_cutting.go new file mode 100644 index 000000000..35256707f --- /dev/null +++ b/codes/go/chapter_greedy/max_product_cutting.go @@ -0,0 +1,28 @@ +// File: max_product_cutting.go +// Created Time: 2023-07-23 +// Author: Reanon (793584285@qq.com) + +package chapter_greedy + +import "math" + +/* 最大切分乘积:贪心 */ +func maxProductCutting(n int) int { + // 当 n <= 3 时,必须切分出一个 1 + if n <= 3 { + return 1 * (n - 1) + } + // 贪心地切分出 3 ,a 为 3 的个数,b 为余数 + a := n / 3 + b := n % 3 + if b == 1 { + // 当余数为 1 时,将一对 1 * 3 转化为 2 * 2 + return int(math.Pow(3, float64(a-1))) * 2 * 2 + } + if b == 2 { + // 当余数为 2 时,不做处理 + return int(math.Pow(3, float64(a))) * 2 + } + // 当余数为 0 时,不做处理 + return int(math.Pow(3, float64(a))) +} diff --git a/codes/go/chapter_greedy/max_product_cutting_test.go b/codes/go/chapter_greedy/max_product_cutting_test.go new file mode 100644 index 000000000..e931d6854 --- /dev/null +++ b/codes/go/chapter_greedy/max_product_cutting_test.go @@ -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) +}