贪心算法(集合覆盖问题)
贪心算法介绍
- 贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法
- 贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果
应用场景-集合覆盖问题
问题详情
假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号
![](https://img-blog.csdnimg.cn/img_convert/867402afc2c38e0ed85d9e65bdba7d85.png)
思路分析
- 目前并没有算法可以快速计算得到准备的值, 使用贪婪算法,则可以得到非常接近的解,并且效率高。选择策略上,因为需要覆盖全部地区的最小集合:
- 遍历所有的广播电台, 找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系)
- 将这个电台加入到一个集合中(比如 ArrayList), 想办法把该电台覆盖的地区在下次比较时去掉。
- 重复第 1 步直到覆盖了全部的地区
图解:
![](https://img-blog.csdnimg.cn/img_convert/d9891377d85c71dcf05d306b769fef78.png)
实现代码:
package com.edu.algorithm.贪心算法;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* <p>
* 假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号
* </p>
*
* @作者 five-five
* @创建时间 2020/9/1
*/
public class 集合覆盖 {
public static void main(String[] args) {
//储存结果
List<Integer> nums = new ArrayList<>();
String[] k1 = {"北京", "上海", "天津"};
String[] k2 = {"广州", "北京", "深圳"};
String[] k3 = {"成都", "上海", "杭州"};
String[] k4 = {"上海", "天津"};
String[] k5 = {"杭州", "大连"};
String[][] all = {k1, k2, k3, k4, k5};
//把所有集合的元素都拿一遍(去重)
HashSet<String> hashSet = new HashSet<>();
for (String[] s : all) {
for (String string : s) {
hashSet.add(string);
}
}
System.out.println(hashSet);
//开始比较(来获得maxkey)
int[] key=null;
do {
key = new int[all.length];
for (int i = 0; i < all.length; i++) {
for (int j = 0; j < all[i].length; j++) {
//开始来弄key
if (hashSet.contains(all[i][j])) {
key[i]+=1;
}
}
}
//拿到key值,弄一个maxkey的下标出来
int max=0;
for (int k=0;k<key.length;k++){
if (key[max]<key[k]) {
max=k;
}
}
nums.add(max);
//开始删除内容
for (String s : all[max]) {
if (hashSet.contains(s)) {
hashSet.remove(s);
}
}
} while (isReady(key));//key全部为0的时候
nums.remove(nums.size()-1);
//打印结果
for (Integer num : nums) {
System.out.print("k"+(num+(Integer) 1)+"\t");
}
}
private static boolean isReady(int[] key) {
for (int i:key){
if(i!=0){
return true;
}
}
return false;
}
}