diff --git a/codes/kotlin/chapter_greedy/coin_change_greedy.kt b/codes/kotlin/chapter_greedy/coin_change_greedy.kt new file mode 100644 index 000000000..32fce1f67 --- /dev/null +++ b/codes/kotlin/chapter_greedy/coin_change_greedy.kt @@ -0,0 +1,53 @@ +/** + * File: coin_change_greedy.kt + * Created Time: 2024-01-25 + * Author: curtishd (1023632660@qq.com) + */ + +package chapter_greedy + +/* 零钱兑换:贪心 */ +fun coinChangeGreedy(coins: IntArray, amt: Int): Int { + // 假设 coins 列表有序 + var am = amt + var i = coins.size - 1 + var count = 0 + // 循环进行贪心选择,直到无剩余金额 + while (am > 0) { + // 找到小于且最接近剩余金额的硬币 + while (i > 0 && coins[i] > am) { + i-- + } + // 选择 coins[i] + am -= coins[i] + count++ + } + // 若未找到可行方案,则返回 -1 + return if (am == 0) count else -1 +} + +/* Driver Code */ +fun main() { + // 贪心:能够保证找到全局最优解 + var coins = intArrayOf(1, 5, 10, 20, 50, 100) + var amt = 186 + var res = coinChangeGreedy(coins, amt) + println("\ncoins = ${coins.contentToString()}, amt = $amt") + println("凑到 $amt 所需的最少硬币数量为 $res") + + // 贪心:无法保证找到全局最优解 + coins = intArrayOf(1, 20, 50) + amt = 60 + res = coinChangeGreedy(coins, amt) + println("\ncoins = ${coins.contentToString()}, amt = $amt") + println("凑到 $amt 所需的最少硬币数量为 $res") + println("实际上需要的最少数量为 3 ,即 20 + 20 + 20") + + // 贪心:无法保证找到全局最优解 + coins = intArrayOf(1, 49, 50) + amt = 98 + res = coinChangeGreedy(coins, amt) + println("\ncoins = ${coins.contentToString()}, amt = $amt") + println("凑到 $amt 所需的最少硬币数量为 $res") + println("实际上需要的最少数量为 2 ,即 49 + 49") +} \ No newline at end of file diff --git a/codes/kotlin/chapter_greedy/fractional_knapsack.kt b/codes/kotlin/chapter_greedy/fractional_knapsack.kt new file mode 100644 index 000000000..0b375b66c --- /dev/null +++ b/codes/kotlin/chapter_greedy/fractional_knapsack.kt @@ -0,0 +1,57 @@ +/** + * File: fractional_knapsack.kt + * Created Time: 2024-01-25 + * Author: curtishd (1023632660@qq.com) + */ + +package chapter_greedy + +import java.util.* + +/* 物品 */ +class Item( + val w: Int, // 物品 + val v: Int // 物品价值 +) + +/* 分数背包:贪心 */ +fun fractionalKnapsack( + wgt: IntArray, + value: IntArray, + c: Int +): Double { + // 创建物品列表,包含两个属性:重量、价值 + var cap = c + val items = arrayOfNulls(wgt.size) + for (i in wgt.indices) { + items[i] = Item(wgt[i], value[i]) + } + // 按照单位价值 item.v / item.w 从高到低进行排序 + Arrays.sort(items, Comparator.comparingDouble { item: Item -> -(item.v.toDouble() / item.w) }) + // 循环贪心选择 + var res = 0.0 + for (item in items) { + if (item!!.w <= cap) { + // 若剩余容量充足,则将当前物品整个装进背包 + res += item.v.toDouble() + cap -= item.w + } else { + // 若剩余容量不足,则将当前物品的一部分装进背包 + res += item.v.toDouble() / item.w * cap + // 已无剩余容量,因此跳出循环 + break + } + } + return res +} + +/* Driver Code */ +fun main() { + val wgt = intArrayOf(10, 20, 30, 40, 50) + val values = intArrayOf(50, 120, 150, 210, 240) + val cap = 50 + + // 贪心算法 + val res = fractionalKnapsack(wgt, values, cap) + println("不超过背包容量的最大物品价值为 $res") +} \ No newline at end of file diff --git a/codes/kotlin/chapter_greedy/max_capacity.kt b/codes/kotlin/chapter_greedy/max_capacity.kt new file mode 100644 index 000000000..ea9edfe27 --- /dev/null +++ b/codes/kotlin/chapter_greedy/max_capacity.kt @@ -0,0 +1,41 @@ +/** + * File: max_capacity.kt + * Created Time: 2024-01-25 + * Author: curtishd (1023632660@qq.com) + */ + +package chapter_greedy + +import kotlin.math.max +import kotlin.math.min + +/* 最大容量:贪心 */ +fun maxCapacity(ht: IntArray): Int { + // 初始化 i, j,使其分列数组两端 + var i = 0 + var j = ht.size - 1 + // 初始最大容量为 0 + var res = 0 + // 循环贪心选择,直至两板相遇 + while (i < j) { + // 更新最大容量 + val cap = (min(ht[i].toDouble(), ht[j].toDouble()) * (j - i)).toInt() + res = max(res.toDouble(), cap.toDouble()).toInt() + // 向内移动短板 + if (ht[i] < ht[j]) { + i++ + } else { + j-- + } + } + return res +} + +/* Driver Code */ +fun main() { + val ht = intArrayOf(3, 8, 5, 2, 7, 7, 3, 4) + + // 贪心算法 + val res = maxCapacity(ht) + println("最大容量为 $res") +} \ No newline at end of file diff --git a/codes/kotlin/chapter_greedy/max_product_cutting.kt b/codes/kotlin/chapter_greedy/max_product_cutting.kt new file mode 100644 index 000000000..9a24ce756 --- /dev/null +++ b/codes/kotlin/chapter_greedy/max_product_cutting.kt @@ -0,0 +1,39 @@ +/** + * File: max_product_cutting.kt + * Created Time: 2024-01-25 + * Author: curtishd (1023632660@qq.com) + */ + +package chapter_greedy + +import kotlin.math.pow + +/* 最大切分乘积:贪心 */ +fun maxProductCutting(n: Int): Int { + // 当 n <= 3 时,必须切分出一个 1 + if (n <= 3) { + return 1 * (n - 1) + } + // 贪心地切分出 3 ,a 为 3 的个数,b 为余数 + val a = n / 3 + val b = n % 3 + if (b == 1) { + // 当余数为 1 时,将一对 1 * 3 转化为 2 * 2 + return 3.0.pow((a - 1).toDouble()).toInt() * 2 * 2 + } + if (b == 2) { + // 当余数为 2 时,不做处理 + return 3.0.pow(a.toDouble()).toInt() * 2 * 2 + } + // 当余数为 0 时,不做处理 + return 3.0.pow(a.toDouble()).toInt() +} + +/* Driver Code */ +fun main() { + val n = 58 + + // 贪心算法 + val res = maxProductCutting(n) + println("最大切分乘积为 $res") +}