java贪心算法案例

1.零钱找回问题

这个问题在我们的日常生活中就更加普遍了。假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元,至少要用多少张纸币?用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可。在日常生活中我们自然而然也是这么做的。在程序中已经事先将Value按照从小到大的顺序排好。

2.背包问题:

背包容量=50; w[]={10,20,30} ,p[]={60,100,120} 用贪心选择(10+20)<50,p=160,但这并不是最优解,事实上(20+30)=50,p=100+120=220.才是问题的解。对于01背包,贪心采用自上而下,拆分子问题的方式为:{物品1,物品2,物品3}—>{物品2,物品3}----{物品3}…它无法保证最终能将背包装满,部分闲置的背包空间使每千克背包空间的价值降低了.
对于该问题,我们应该采用自下而上的动态规划来求解,拆分子问题的 方式为:{物品1}-------->{物品1,物品2}------>{物品1,物品2,物品3}.在求解时,应比较,选择该物品和不选择该物品,所导致的最终方案,然后再做出最好选择,为了更快求出问题的解。动态规划还记忆了过程中产生的许多互相重叠的子问题的答案。

代码

import cn.hutool.core.collection.CollUtil;

import java.util.*;

/**
 * desc: 算法测试
 *
 * @author qts
 * @date 2023/7/19 0019
 */
public class AlgorithmTest {



    public static void main(String[] args) {
        // 测试找零钱
        //System.out.println(change(320));

        // 测试背包问题
        List<HashMap<String, Object>> maps = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("weight", 10f);
        map.put("value",60f);
        map.put("name", "物品1");
        maps.add(map);

        map = new HashMap<String, Object>();
        map.put("weight", 30f);
        map.put("value",120f);
        map.put("name", "物品3");
        maps.add(map);

        map = new HashMap<String, Object>();
        map.put("weight", 20f);
        map.put("value",100f);
        map.put("name", "物品2");
        maps.add(map);

        sortByUnitValue(maps);
        System.out.println("物品列表: "+maps);

        List backpack = backpack(50f, maps.toArray(new HashMap[3]));

        System.out.println("结果: "+backpack);

    }

    // 钱面值
    public static int[] moneys = {100, 50, 20, 10, 5, 2, 1};
    // 对应面值的数量
    public static int[] counts = {5, 3, 0, 1, 2, 0, 3};

    /**
     * 贪心算法: 找零钱
     * @param amount 金额
     */
    public static String change(int amount) {
        StringBuilder result = new StringBuilder(amount + " = ");

        for (int i = 0; i < moneys.length; i++) {
            if (amount <= 0) {
                break;
            }

            int curMoneyCount = Math.min(amount / moneys[i], counts[i]);

            amount = amount - curMoneyCount * moneys[i];
            if (curMoneyCount > 0) {
                if (i > 0) {
                    result.append(" + ");
                }
                result.append(curMoneyCount).append("张").append(moneys[i]);
            }

        }

        if (amount > 0) {
            return "无解";
        }

        return result.toString();
    }


    /**
     * 单位价值倒序
     * @param maps
     */
    private static void sortByUnitValue(List<HashMap<String, Object>> maps) {
        CollUtil.sort(maps, new Comparator<HashMap<String, Object>>() {
            @Override
            public int compare(HashMap<String, Object> o1, HashMap<String, Object> o2) {
                Float weight1 = (Float) o1.get("weight");
                Float value1 = (Float) o1.get("value");
                Float unitValue1 = value1/weight1; // 单位重量的价值

                Float weight2 = (Float) o2.get("weight");
                Float value2 = (Float) o2.get("value");
                Float unitValue2 = value2/weight2; // 单位重量的价值

                return (int) ((unitValue2 - unitValue1));
            }
        });
    }

    /**
     * 贪心算法: 背包问题
     * @param capacity 背包容量
     * @param maps 物品,从最优到最次排序
     * @return
     */
    public static List<HashMap<String,Object>> backpack(Float capacity,HashMap<String,Object>[] maps) {
        List<HashMap<String,Object>> result = new ArrayList<HashMap<String, Object>>();

        for (int i = 0; i < maps.length; i++) {
            if (capacity <= 0) {
                break;
            }

            HashMap<String, Object> goods = maps[i];
            Float weight = (Float) goods.get("weight");// 重量
            Float value = (Float) goods.get("value");// 价值
            String name = (String) goods.get("name");// 名称

            Float unitValue = value/weight; // 单位重量的价值

            float min = Math.min(capacity, weight);

            capacity -= min;// 剩余背包容量

            HashMap<String, Object> map = new HashMap<>();
            map.put("weight",min);
            map.put("name",name);

            result.add(map);
        }

        return result;

    }

}

结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 贪心算法是一种在每一步选择中都采取在当前状态下最优决策的算法。它所做出的决策一般不会改变后面的最优决策,因此它的决策过程是没有后效性的。 在Java中实现贪心算法需要以下几步: 1. 定义算法的目标,也就是最优解,以及算法要达到的目标状态。 2. 对于每一个状态,求出它的所有可能的决策,并且确定每一个决策的优劣。 3. 根据决策的优劣选择最优决策。 4. 在每一步选择完最优决策之后,更新算法的状态,并进入下一步。 5. 当算法达到目标状态时,停止算法并输出最优解。 例如,我们要实现一个贪心算法来求解最小生成树问题,那么我们可以这样做: 1. 定义算法的目标,即求出一颗最小生成树。 2. 对于每一个状态,求出它的所有可能的决策,也就是加入一条新的边。 3. 对于每一条边,计算它的费用,并根据费用的大小选择最小的边。 4. 将最小的边加入生成树中,并更新 ### 回答2: 贪心算法是一种常用的算法思想,它在每一步的选择中都会选择当前情况下的最优解,以期望最终得到全局最优解。Java语言可以相对容易地实现贪心算法。 实现贪心算法的关键是找到一个具备贪心选择性质和最优子结构的问题。贪心选择性质是指通过局部最优解能够得到全局最优解,而最优子结构是指一个问题的最优解可以由其子问题的最优解来构造。通过找到贪心选择和最优子结构,可以将问题划分为独立的子问题进行求解。 在实现贪心算法时,一般需要以下三个步骤: 1. 定义问题的解空间和组成解的元素。 2. 设计一个维护当前解的贪心策略函数,该函数通过从解空间中选择最优元素来构建当前解。 3. 设计一个验证当前解是否满足问题要求的函数。 举个例子来说明,假设有一组区间[start, end],需要选择一些区间,使得它们之间不重叠,并且所选择的区间尽量多。可以按照区间的结束位置进行升序排序,然后遍历区间列表。对于每个区间,如果它的开始位置大于前一个区间的结束位置,就将该区间加入当前解。通过这种贪心选择策略,可以得到最多的不重叠区间。 具体的Java代码实现如下: ```java import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; class Interval { int start; int end; public Interval(int start, int end) { this.start = start; this.end = end; } } public class GreedyAlgorithm { public static void main(String[] args) { List<Interval> intervals = Arrays.asList( new Interval(1, 3), new Interval(2, 4), new Interval(3, 5), new Interval(4, 6) ); List<Interval> selectedIntervals = selectNonOverlappingIntervals(intervals); System.out.println("Selected Intervals: "); for (Interval interval : selectedIntervals) { System.out.println("[" + interval.start + ", " + interval.end + "]"); } } public static List<Interval> selectNonOverlappingIntervals(List<Interval> intervals) { List<Interval> selectedIntervals = new ArrayList<>(); // 按结束位置升序排序 intervals.sort(Comparator.comparingInt(interval -> interval.end)); int end = Integer.MIN_VALUE; for (Interval interval : intervals) { if (interval.start >= end) { selectedIntervals.add(interval); end = interval.end; } } return selectedIntervals; } } ``` 以上代码使用Java实现了一种贪心算法,通过选择结束位置最早的区间来得到不重叠的区间。当然,贪心算法只适用于具备贪心选择性质和最优子结构的问题,对于其他类型的问题可能需要选择其他的算法思想来解决。 ### 回答3: 贪心算法是一种常用的问题求解方法,它通过每一步都选择当前情况下最优的选择,从而达到整体最优解的目的。贪心算法在解决一些最优化问题中特别有效。 在Java中,实现贪心算法的一般步骤如下: 1. 确定问题的最优子结构:通过分析问题,确定在每一步选择中都能得到最优解的子结构。 2. 构建贪心选择的步骤:根据问题的最优子结构,确定每一步选择最优解的策略。 3. 构建问题的贪心算法解:按照选择的步骤,逐步选择最优解,得到问题的贪心算法解。 4. 证明贪心选择的正确性:通过数学证明或实例分析,证明贪心选择是正确的。 5. 分析算法的时间复杂度:评估算法的效率,确保算法能够在合理的时间范围内解决问题。 举个例子来说明贪心算法的实现过程:假设有一组不同面额的硬币和一个要凑出的金额。要求使用最少的硬币凑出指定金额。 首先,我们需要确定最优子结构,即在每一步选择中,都能得到最优解的子结构。在硬币凑数问题中,最优解的子结构是每次选择面值最大的硬币。 然后,我们构建贪心选择的步骤。按照面值最大的硬币选择,直到凑出指定金额。 接下来,我们构建问题的贪心算法解。根据贪心选择的步骤,我们每次选择面值最大的硬币,直到凑出指定金额。 最后,我们需要证明贪心选择的正确性。在硬币凑数问题中,贪心选择是正确的,因为面值最大的硬币一定是凑出指定金额最有效的选择。 通过以上步骤,我们可以实现Java中的贪心算法来解决问题。需要注意的是,贪心算法并不适用于所有问题,只适用于一些具有贪心选择性质的问题。因此,在应用贪心算法之前,我们需要对问题进行充分的分析和推理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值