贪心算法
应用场景-集合覆盖问题
假设在下面需要付费的广播台,以及广播台新型号可以覆盖的地区,如何选择最少的广播台,让所有地区都可以接收到信号
广播台覆盖地区
k1
北京、上海、天津
k2
广州、北京、深圳
k3
成都、上海、杭州
k4
上海、天津
k5
杭州、大连
贪心算法介绍
贪心算法指在对问题进行求解时,在每一步选择中都选择最好或者最优的选择,从而得到结果最好或最优
局部最优——>结果最优
贪心算法所得的结果不一定是最优的结果,但是都近似于最优解
集合覆盖思路分析
遍历所有的广播电台,找到一个覆盖了最多未覆盖地区的电台
将这个电台加入到一个集合中,想办法把该电台覆盖地区在下次比较时去掉
重复第1步直到覆盖了所有地区
代码实现
package whyAlgorithm.greedy_algorithm;
import java.util.*;
/**
* @Description TODO 结合覆盖问题的贪心算法
* @Author why
* @Date 2020/12/20 19:53
* Version 1.0
**/
public class SetCover {
public static void main(String[] args) {
//创建广播电台及其覆盖地区
HashMap> broadcasts = new HashMap<>();
//将各个电台放入
HashSet hashSet1 = new HashSet<>();
hashSet1.add("北京");
hashSet1.add("上海");
hashSet1.add("天津");
HashSet hashSet2 = new HashSet<>();
hashSet2.add("广州");
hashSet2.add("北京");
hashSet2.add("深圳");
HashSet hashSet3 = new HashSet<>();
hashSet3.add("成都");
hashSet3.add("上海");
hashSet3.add("杭州");
HashSet hashSet4 = new HashSet<>();
hashSet4.add("上海");
hashSet4.add("天津");
HashSet hashSet5 = new HashSet<>();
hashSet4.add("杭州");
hashSet4.add("大连");
broadcasts.put("k1",hashSet1);
broadcasts.put("k2",hashSet2);
broadcasts.put("k3",hashSet3);
broadcasts.put("k4",hashSet4);
broadcasts.put("k5",hashSet5);
//存放所有地区
HashSet allAreas = new HashSet<>();
allAreas.add("北京");
allAreas.add("上海");
allAreas.add("天津");
allAreas.add("广州");
allAreas.add("深圳");
allAreas.add("成都");
allAreas.add("杭州");
allAreas.add("大连");
//创建list集合存放选择的电台集合
ArrayList selects = new ArrayList<>();
//定义一个林试集合保存在遍历过程中的电台覆盖地区和当前还没有覆盖的地区的交集
HashSet tempSet = new HashSet<>();
//定义变量,保存在一次遍历过程中能够覆盖最大未覆盖的地区对应电台的key
//如果maxKey不为null,则加入到selects
String maxKey = null;
while (allAreas.size() != 0){//allAreas.size() != 0表示还没有覆盖到所有地区
//没进行一次循环将maxKey置空
maxKey = null;
//遍历boradcasts,取出电台key
for (String key : broadcasts.keySet()
) {
//每进行一次将tempSet集合置空
tempSet.clear();
//当前key覆盖的地区
HashSet areas = broadcasts.get(key);
tempSet.addAll(areas);
//求出tempSet和allAreas的交集
//交集会赋值给tempSet
tempSet.retainAll(allAreas);
//如果当前集合包含的未覆盖地区的数列,比maxKey指向的集合未覆盖的地区还多
//maxKey就需要充值
//体现贪婪算法,每次选择最优
if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())){
maxKey = key;
}
}
if (maxKey != null){//选中了电台
//将maxKey加入到selects中
selects.add(maxKey);
//将maxKey指向的电台覆盖的地区从allAreas取出
allAreas.removeAll(broadcasts.get(maxKey));
}
}
//得到的选择结果
System.out.println("得到的选择结果"+selects);
}
}
注意事项
贪心算法所得结果不一定是最优解