编程中十大常用算法:(五)贪婪算法

理论介绍

贪婪算法(又称贪心算法)是指在对问题进行求解时,在每一步中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。
贪婪算法所得到的结果不一定是最优的结果(有时会是最优解),但是都是近似最优解的结果。

实际运用-集合覆盖

问题:
假设存在如下表所示需要付费的广播台,以及广播台信息可以覆盖的地区。如何选择最少的广播台,让所有的地区都可以接收到信号。编程中十大常用算法:(五)贪婪算法_第1张图片
穷举法:
列出每个可能的广播台的集合,这被称为幂集。假设共有n个广播台,则广播台的组合共用2n-1个,效率低。

解决办法:
贪婪算法

分析:
(1)目前并没有算法可以快速计算得到准确的值,使用贪婪算法,可以得到非常接近最优的解,并且效率高。
(2)遍历所有的广播台,找到一个覆盖了最多覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系)。
(3)将这个电台加入到一个集合中,想办法把该电台覆盖的地区在下次比较时去掉。
(4)重复第一步直到覆盖了全部地区。

代码实现(Java)



package com.zq.greedy;

 

import java.util.ArrayList;

import java.util.HashMap;

import java.util.HashSet;

 

public class greedy {

  public static void main(String[] args) {

     HashMap<String,HashSet<String>> broadcasts = new HashMap<String, HashSet<String>>();

     //将各个电台放入到broadcasts

     HashSet<String> hashSet1 = new HashSet<String>();

     hashSet1.add("北京");

     hashSet1.add("上海");

     hashSet1.add("天津");

     

     HashSet<String> hashSet2 = new HashSet<String>();

     hashSet2.add("广州");

     hashSet2.add("北京");

     hashSet2.add("深圳");

     

     HashSet<String> hashSet3 = new HashSet<String>();

     hashSet3.add("成都");

     hashSet3.add("上海");

     hashSet3.add("杭州");

     

     

     HashSet<String> hashSet4 = new HashSet<String>();

     hashSet4.add("上海");

     hashSet4.add("天津");

     

     HashSet<String> hashSet5 = new HashSet<String>();

     hashSet5.add("杭州");

     hashSet5.add("大连");

  

     //加入到map

     broadcasts.put("K1", hashSet1);

     broadcasts.put("K2", hashSet2);

     broadcasts.put("K3", hashSet3);

     broadcasts.put("K4", hashSet4);

     broadcasts.put("K5", hashSet5);

     

     //allAreas 存放所有的地区

     HashSet<String> allAreas = new HashSet<String>();

     allAreas.add("北京");

     allAreas.add("上海");

     allAreas.add("天津");

     allAreas.add("广州");

     allAreas.add("深圳");

     allAreas.add("成都");

     allAreas.add("杭州");

     allAreas.add("大连");

     

     //创建ArrayList,存放选择的电台

     ArrayList<String> selects=new ArrayList<>();

     //定义临时集合,在遍历过程中,存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集

     HashSet<String> tempSet=new HashSet<>();

     //定义maxKey,保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的key

     //如果maxKey不为null,则会加入到selects

     String maxKey=null;

     

     while(allAreas.size()!=0) {

         maxKey=null;

       //遍历broadcasts,取出对应key

       for(String key:broadcasts.keySet()) {

          tempSet.clear();

          //当前key能覆盖的地区

          HashSet<String> 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) {

            selects.add(maxKey);

            //将maxKey指向的广播电台覆盖地区,从allAreas去掉

           allAreas.removeAll(broadcasts.get(maxKey));

          }

     }

     System.out.println("选择结果为:"+selects);

  }

}

 

结果

在这里插入图片描述

参考文献:
1.韩顺平-图解java数据结构和算法

你可能感兴趣的:(java,数据结构)