常用十大算法_贪心算法

贪心算法 

 贪心算法本质就是在对问题求解时,每一步都选最优的结果,这些每步最优结果汇集成问题的最终结果。但这个最终结果不一定是最优结果。因为每一步可能存在多个最优解,贪心算法只会按照顺序选择其中一个。

【例子】存在下表中的站点K1~5,每个站点对应不同的覆盖城市,需要选择最少的站点,覆盖全部城市

站点覆盖城市
K1北京,上海,天津
K2广州,北京,深圳
K3成都,上海,杭州
K4上海,天津
K5杭州,大连

算法分析: 

注意上述每步中的最优解有可能不止一个,比如说:allAreas中只剩杭州时,K3和K5交集大小都为1,按照顺序取得的策略,贪心算法会选择K3,而不是K5。如果选择K5花的钱比K3少时,贪心算法获得的结果就不算最优了,但它一定满足都覆盖。根据贪心算法的原理,我们需要一个maxKey指针和Key指针,还需要一个集合allAreas用于存储全部城市。每次循环key指针从K1指到K5,而maxKey指针用于指向循环中,覆盖城市与全部城市交集最大的Kn站点(取得每步的最优解),当5个站点都循环完后,需要把maxKey指向的站点加入到一个专门存储解的集合selects中,同时要删除allAreas中Kn覆盖城市的部分,并重置maxKey。再进行循环,直到allAreas集合大小为0时结束。

代码实现:(注意这里面用了maxKeySize,用于保存交集大小,方便下一次循环产生的交集与之比较,找到最优站点)

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.greedyAlgorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class 贪心算法_greedyAlgorithm_子集覆盖问题 {
    public static void main(String[] args) {
        //创建各站点
        HashMap<String, HashSet<String>> broad= new HashMap<>();
        HashSet<String> place1=new HashSet<>();
        place1.add("北京");
        place1.add("上海");
        place1.add("天津");
        HashSet<String> place2=new HashSet<>();
        place2.add("北京");
        place2.add("广州");
        place2.add("深圳");
        HashSet<String> place3=new HashSet<>();
        place3.add("成都");
        place3.add("上海");
        place3.add("杭州");
        HashSet<String> place4=new HashSet<>();
        place4.add("上海");
        place4.add("天津");
        HashSet<String> place5=new HashSet<>();
        place5.add("杭州");
        place5.add("大连");
        broad.put("K1",place1);
        broad.put("K2",place2);
        broad.put("K3",place3);
        broad.put("K4",place4);
        broad.put("K5",place5);

        //创建需要覆盖的城市集合
        HashSet<String> allAreas=new HashSet<>();
        allAreas.add("北京");
        allAreas.add("上海");
        allAreas.add("天津");
        allAreas.add("广州");
        allAreas.add("深圳");
        allAreas.add("成都");
        allAreas.add("杭州");
        allAreas.add("大连");

        //创建一个集合用于存储贪心算法每轮所选择的站点
        ArrayList<String> selects=new ArrayList<>();

        //创建一个临时集合,用于存储每个站点覆盖的城市
        HashSet<String> tempSet=new HashSet<>();
        //用于保存循环中的最优站点
        String maxKey=null;
        //用于保存循环中maxKey对应的站点与allAreas的交集大小
        int maxKeySize=0;
        while (allAreas.size()>0){//allAreas长度大于0,说明还有城市未必覆盖
            for (String key:broad.keySet()) {//应用贪心算法获取最优站点解
                tempSet.addAll(broad.get(key));//获取key站点对应的所有城市
                tempSet.retainAll(allAreas);//将tempSet的数据与allAreas数据求交集,并赋给tempSet
                //tempSet.size()>maxKeySize这句话就是贪心算法的应用
                if (tempSet.size()>0 && (maxKey==null || tempSet.size()>maxKeySize)){
                    maxKey=key;
                    maxKeySize=tempSet.size();//保存本次的交集大小,方便下一次循环产生的交集与之比较,找到最优站点
                }
                tempSet.clear();//清空,方便下次循环取值
            }
            if (maxKey!=null){//说明找到了本次循环的最优站点
                selects.add(maxKey);//将找到的最优站点加入到结果集合中
                allAreas.removeAll(broad.get(maxKey));//从未覆盖城市集合中删除maxKey对应站点的城市
                maxKey=null;//置空
                maxKeySize=0;//置零
            }
        }
        System.out.println("贪心算法筛选的解为="+selects);
    }
}
贪心算法筛选的解为=[K1, K2, K3, K5]

 


其他常用算法,见下各链接

【常用十大算法_二分查找算法】

【常用十大算法_分治算法】

【常用十大算法_动态规划算法(DP)】

【常用十大算法_KMP算法】

【常用十大算法_普里姆(prim)算法,克鲁斯卡尔(Kruskal)算法】

【常用十大算法_迪杰斯特拉(Dijkstra)算法,弗洛伊德(Floyd)算法】

【常用十大算法_回溯算法】

 

【数据结构与算法整理总结目录 :>】<-- 宝藏在此(doge)  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值