贪心算法以及简单示例Java实现

本文介绍了贪心算法的基本概念和步骤,通过集合覆盖问题的具体实例详细解释了如何利用贪心策略找到局部最优解,并最终实现全局最优的目标。同时提供了完整的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基本概念

  贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。也就是说,不从整体最优上加以考虑,做出的只是在某种意义上的局部最优解。

二、算法步骤

贪心算法一般按照如下步骤进行:

  1. 建立数学模型来描述问题
  2. 把待求解的问题分解位若干个子问题
  3. 对每个子问题进行求解,得到局部最优解
  4. 把子问题的局部最优解合并为原问题的一个解

简单来说,就是在进行每一步选择时,都基于当前步,选择最优的解。

这里我们以一个简单的集合覆盖问题为例:
假设现有如下几个广播台以及广播信号可以覆盖的地区,如何选择最少的广播,使广播信号可以覆盖所有地区。
在这里插入图片描述
由上题可以得知,现有{北京、上海、天津、广州、深圳、成都、杭州、大连}这几个地区需要覆盖,那么我们在进行选择时,就是每一次尽量覆盖足够多的未被覆盖的地区。

  1. 选择K1,那么此时还有{广州、深圳、成都、杭州、大连}未覆盖
  2. 选择K2,那么此时还有{成都、杭州、大连}未覆盖
  3. 选择K3,那么此时还有{大连}未覆盖
  4. 现在K5,此时已经全部覆盖

三、贪心算法解决集合覆盖问题代码实现

/**
 * @author dankejun
 * @create 2020/9/1816:57
 */
public class GreedyAlgorithm {
    public static void main(String[] args) {
        HashMap<String, HashSet<String>> map = new HashMap<>();
        HashSet<String> hashSet1 = new HashSet();
        hashSet1.add("北京");
        hashSet1.add("上海");
        hashSet1.add("天津");

        HashSet<String> hashSet2 = new HashSet();
        hashSet2.add("广州");
        hashSet2.add("北京");
        hashSet2.add("深圳");

        HashSet<String> hashSet3 = new HashSet();
        hashSet3.add("成都");
        hashSet3.add("上海");
        hashSet3.add("杭州");

        HashSet<String> hashSet4 = new HashSet();
        hashSet4.add("上海");
        hashSet4.add("天津");

        HashSet<String> hashSet5 = new HashSet();
        hashSet5.add("杭州");
        hashSet5.add("大连");

        map.put("k1", hashSet1);
        map.put("k2", hashSet2);
        map.put("k3", hashSet3);
        map.put("k4", hashSet4);
        map.put("k5", hashSet5);
        
        List<String> greedy = greedy(map);
        System.out.println("选择:" + greedy);
    }

    public static List<String> greedy(HashMap<String, HashSet<String>> map) {
        //将所有需要覆盖的地区放到allAreas中
        HashSet<String> allAreas = new HashSet<>();
        Iterator<Map.Entry<String, HashSet<String>>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, HashSet<String>> next = iterator.next();
            allAreas.addAll(next.getValue());
        }
        //对每个电台进行贪心选择
        List<String> selects = new ArrayList<>();//存放选择的电台号的集合
        HashSet<String> tempSet = new HashSet<>();//中间变量,用于求交集
        String maxKey = null;//存放具有最优选择的电台号
        while (allAreas.size() != 0) {//还未被全部覆盖
            maxKey = null;//重置maxKey
            for (String key : map.keySet()) {
                tempSet.clear();//清空临时集合
                HashSet<String> areas = map.get(key);
                tempSet.addAll(areas);
                tempSet.retainAll(allAreas);//求出两个集合的交集,赋值给tempSet
                //如果当前电台覆盖地区数量大于maxKey,就用当前电台号替换maxKey
                if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > map.get(maxKey).size())) {
                    maxKey = key;
                }
            }
            //将当前最优选择加入集合,并在全部地区中删除
            if (maxKey != null) {
                selects.add(maxKey);
                allAreas.removeAll(map.get(maxKey));
            }
        }
        return selects;
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值