From b43de88f716779d054f0dd442565ca5096965140 Mon Sep 17 00:00:00 2001 From: hpstory <33348162+hpstory@users.noreply.github.com> Date: Sat, 22 Jul 2023 02:54:41 +0800 Subject: [PATCH] feat(csharp): add csharp code for charper greedy (#645) --- .../chapter_greedy/coin_change_greedy.cs | 54 ++++++++++++++++++ .../chapter_greedy/fractional_knapsack.cs | 57 +++++++++++++++++++ codes/csharp/chapter_greedy/max_capacity.cs | 39 +++++++++++++ .../chapter_greedy/max_product_cutting.cs | 39 +++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 codes/csharp/chapter_greedy/coin_change_greedy.cs create mode 100644 codes/csharp/chapter_greedy/fractional_knapsack.cs create mode 100644 codes/csharp/chapter_greedy/max_capacity.cs create mode 100644 codes/csharp/chapter_greedy/max_product_cutting.cs diff --git a/codes/csharp/chapter_greedy/coin_change_greedy.cs b/codes/csharp/chapter_greedy/coin_change_greedy.cs new file mode 100644 index 000000000..8d2649e89 --- /dev/null +++ b/codes/csharp/chapter_greedy/coin_change_greedy.cs @@ -0,0 +1,54 @@ +/** +* File: coin_change_greedy.cs +* Created Time: 2023-07-21 +* Author: hpstory (hpstory1024@163.com) +*/ + +namespace hello_algo.chapter_greedy; + +public class coin_change_greedy { + /* 零钱兑换:贪心 */ + public int coinChangeGreedy(int[] coins, int amt) { + // 假设 coins 列表有序 + int i = coins.Length - 1; + int count = 0; + // 循环进行贪心选择,直到无剩余金额 + while (amt > 0) { + // 找到小于且最接近剩余金额的硬币 + while (coins[i] > amt) { + i--; + } + // 选择 coins[i] + amt -= coins[i]; + count++; + } + // 若未找到可行方案,则返回 -1 + return amt == 0 ? count : -1; + } + + [Test] + public void Test() { + // 贪心:能够保证找到全局最优解 + int[] coins = { 1, 5, 10, 20, 50, 100 }; + int amt = 186; + int res = coinChangeGreedy(coins, amt); + Console.WriteLine("\ncoins = " + coins.PrintList() + ", amt = " + amt); + Console.WriteLine("凑到 " + amt + " 所需的最少硬币数量为 " + res); + + // 贪心:无法保证找到全局最优解 + coins = new int[] { 1, 20, 50 }; + amt = 60; + res = coinChangeGreedy(coins, amt); + Console.WriteLine("\ncoins = " + coins.PrintList() + ", amt = " + amt); + Console.WriteLine("凑到 " + amt + " 所需的最少硬币数量为 " + res); + Console.WriteLine("实际上需要的最少数量为 3 ,即 20 + 20 + 20"); + + // 贪心:无法保证找到全局最优解 + coins = new int[] { 1, 49, 50 }; + amt = 98; + res = coinChangeGreedy(coins, amt); + Console.WriteLine("\ncoins = " + coins.PrintList() + ", amt = " + amt); + Console.WriteLine("凑到 " + amt + " 所需的最少硬币数量为 " + res); + Console.WriteLine("实际上需要的最少数量为 2 ,即 49 + 49"); + } +} \ No newline at end of file diff --git a/codes/csharp/chapter_greedy/fractional_knapsack.cs b/codes/csharp/chapter_greedy/fractional_knapsack.cs new file mode 100644 index 000000000..1266edc5d --- /dev/null +++ b/codes/csharp/chapter_greedy/fractional_knapsack.cs @@ -0,0 +1,57 @@ +/** +* File: fractional_knapsack.cs +* Created Time: 2023-07-21 +* Author: hpstory (hpstory1024@163.com) +*/ + +namespace hello_algo.chapter_greedy; + +/* 物品 */ +class Item { + public int w; // 物品重量 + public int v; // 物品价值 + + public Item(int w, int v) { + this.w = w; + this.v = v; + } +} + +public class fractional_knapsack { + /* 分数背包:贪心 */ + public double fractionalKnapsack(int[] wgt, int[] val, int cap) { + // 创建物品列表,包含两个属性:重量、价值 + Item[] items = new Item[wgt.Length]; + for (int i = 0; i < wgt.Length; i++) { + items[i] = new Item(wgt[i], val[i]); + } + // 按照单位价值 item.v / item.w 从高到低进行排序 + Array.Sort(items, (x, y) => (y.v / y.w).CompareTo(x.v / x.w)); + // 循环贪心选择 + double res = 0; + foreach (Item item in items) { + if (item.w <= cap) { + // 若剩余容量充足,则将当前物品整个装进背包 + res += item.v; + cap -= item.w; + } else { + // 若剩余容量不足,则将当前物品的一部分装进背包 + res += (double)item.v / item.w * cap; + // 已无剩余容量,因此跳出循环 + break; + } + } + return res; + } + + [Test] + public void Test() { + int[] wgt = { 10, 20, 30, 40, 50 }; + int[] val = { 50, 120, 150, 210, 240 }; + int cap = 50; + + // 贪心算法 + double res = fractionalKnapsack(wgt, val, cap); + Console.WriteLine("不超过背包容量的最大物品价值为 " + res); + } +} \ No newline at end of file diff --git a/codes/csharp/chapter_greedy/max_capacity.cs b/codes/csharp/chapter_greedy/max_capacity.cs new file mode 100644 index 000000000..97153e083 --- /dev/null +++ b/codes/csharp/chapter_greedy/max_capacity.cs @@ -0,0 +1,39 @@ +/** +* File: max_capacity.cs +* Created Time: 2023-07-21 +* Author: hpstory (hpstory1024@163.com) +*/ + +namespace hello_algo.chapter_greedy; + +public class max_capacity { + /* 最大容量:贪心 */ + public int maxCapacity(int[] ht) { + // 初始化 i, j 分列数组两端 + int i = 0, j = ht.Length - 1; + // 初始最大容量为 0 + int res = 0; + // 循环贪心选择,直至两板相遇 + while (i < j) { + // 更新最大容量 + int cap = Math.Min(ht[i], ht[j]) * (j - i); + res = Math.Max(res, cap); + // 向内移动短板 + if (ht[i] < ht[j]) { + i++; + } else { + j--; + } + } + return res; + } + + [Test] + public void Test() { + int[] ht = { 3, 8, 5, 2, 7, 7, 3, 4 }; + + // 贪心算法 + int res = maxCapacity(ht); + Console.WriteLine("最大容量为 " + res); + } +} \ No newline at end of file diff --git a/codes/csharp/chapter_greedy/max_product_cutting.cs b/codes/csharp/chapter_greedy/max_product_cutting.cs new file mode 100644 index 000000000..5058517c3 --- /dev/null +++ b/codes/csharp/chapter_greedy/max_product_cutting.cs @@ -0,0 +1,39 @@ +/** +* File: max_product_cutting.cs +* Created Time: 2023-07-21 +* Author: hpstory (hpstory1024@163.com) +*/ + +namespace hello_algo.chapter_greedy; + +public class max_product_cutting { + /* 最大切分乘积:贪心 */ + public int maxProductCutting(int n) { + // 当 n <= 3 时,必须切分出一个 1 + if (n <= 3) { + return 1 * (n - 1); + } + // 贪心地切分出 3 ,a 为 3 的个数,b 为余数 + int a = n / 3; + int b = n % 3; + if (b == 1) { + // 当余数为 1 时,将一对 1 * 3 转化为 2 * 2 + return (int)Math.Pow(3, a - 1) * 2 * 2; + } + if (b == 2) { + // 当余数为 2 时,不做处理 + return (int)Math.Pow(3, a) * 2; + } + // 当余数为 0 时,不做处理 + return (int)Math.Pow(3, a); + } + + [Test] + public void Test() { + int n = 58; + + // 贪心算法 + int res = maxProductCutting(n); + Console.WriteLine("最大切分乘积为" + res); + } +} \ No newline at end of file