赞
踩
贪心算法
贪心算法本质就是在对问题求解时,每一步都选最优的结果,这些每步最优结果汇集成问题的最终结果。但这个最终结果不一定是最优结果。因为每一步可能存在多个最优解,贪心算法只会按照顺序选择其中一个。
【例子】存在下表中的站点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]
其他常用算法,见下各链接
【常用十大算法_普里姆(prim)算法,克鲁斯卡尔(Kruskal)算法】
【常用十大算法_迪杰斯特拉(Dijkstra)算法,弗洛伊德(Floyd)算法】
【数据结构与算法整理总结目录 :>】<-- 宝藏在此(doge)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。