贪心算法(集合覆盖问题)
贪心算法介绍
- 贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法
- 贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果
应用场景-集合覆盖问题
问题详情
假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号
思路分析
- 目前并没有算法可以快速计算得到准备的值, 使用贪婪算法,则可以得到非常接近的解,并且效率高。选择策略上,因为需要覆盖全部地区的最小集合:
- 遍历所有的广播电台, 找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系)
- 将这个电台加入到一个集合中(比如 ArrayList), 想办法把该电台覆盖的地区在下次比较时去掉。
- 重复第 1 步直到覆盖了全部的地区
图解:
实现代码:
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)+" "); } } private static boolean isReady(int[] key) { for (int i:key){ if(i!=0){ return true; } } return false; } }