• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
百事可爱
一起努力鸭~~~
博客园    首页    新随笔    联系   管理    订阅  订阅
贪心算法

贪心算法

  1. 贪心算法(又称贪婪算法)是指,在对问题求解时,在每一步选择中都采取最好或最优/最有利的选择,从而希望能够导致结果是最好的算法。
  2. 贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯

3. 应用场景:集合覆盖

已知广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号。

广播台 覆盖地区
K1 "北京", "上海", "天津"
K2 "广州", "北京", "深圳"
K3 "成都", "上海", "杭州"
K4 "上海", "天津"
K5 "杭州", "大连"

思路分析:

首先将要覆盖的所有地区放在一个集合allAreas中,还需要3个索引(起到遍历作用),

集合selects用来存放选中的合适的电台。

  1. 遍历所有的电台,找到一个覆盖了最多未覆盖的地区的电台(此电台可能已经包含一些已覆盖的地区)
  2. 将这个电台加入到一个集合中,想办法把该电台覆盖的地区在下次比较时在allAreas集合中去掉

以下是分步解析:

  1. 用key去遍历所有的电台,找到一个覆盖了最多未覆盖的地区的电台(以allAreas集合中的元素为参照,在遍历所有电台的同时,也有另一个索引i去遍历集合selects),k1到k5对应的地区数:3 , 3 ,3, 2 , 2 ; 则k1就是本次遍历的最多覆盖了未覆盖的地区的电台,令索引 maxKey 指向k1, 并且把k1放进集合selects中,然后将k1所覆盖的城市在allAreas集合中去掉,allAreas={"广州","深圳","成都","杭州","大连"} maxKey置空
  2. 再用key去遍历所有的电台,k1到k5对应的地区数:0 , 2 ,2, 0 , 2 ; 则k2就是本次遍历的最多覆盖了未覆盖的地区的电台,令索引 maxKey 指向k2, 并且把k2放进集合selects中,然后将k2所覆盖的城市在allAreas集合中去掉,allAreas={ "成都","杭州","大连"} , maxKey置空
  3. 再用key去遍历所有的电台,k1到k5对应的地区数:0 , 0 ,2, 0 , 2 ; 则k3就是本次遍历的最多覆盖了未覆盖的地区的电台,令索引 maxKey 指向k3, 并且把k3放进集合selects中,然后将k3所覆盖的城市在allAreas集合中去掉,allAreas={ "大连"} , maxKey置空
  4. 再用key去遍历所有的电台,k1到k5对应的地区数:0 , 0 ,0, 0 , 1 ; 则k5就是本次遍历的最多覆盖了未覆盖的地区的电台,令索引 maxKey 指向k5, 并且把k5放进集合selects中,然后将k5所覆盖的城市在allAreas集合中去掉,allAreas={ } ,
  5. 此时,allAreas为空,不需要再遍历,selects=
package 贪心算法;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class TanXin {

	public static void main(String[] args) {

		// 创建广播电台,放入到Map集合中 Map<k,v>
		HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
		// 将各个电台放入到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<String>();

		// 定义一个临时的集合, 在遍历的过程中,存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集
		HashSet<String> tempSet = new HashSet<String>();

		// 定义给maxKey , 保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的key;如果maxKey 不为null , 则会加入到 selects
		 
		String maxKey = null;
		
		while (allAreas.size() != 0) { // 如果allAreas 不为0, 则表示还没有覆盖到所有的地区
			
			// 每进行一次while(每次把maxkey指向的电台被放入selects后),需要清空maxkey ,置为null
			maxKey = null;

			// 遍历 broadcasts, 取出对应key 这个for是用来找到最优的maxkey
			for (String key : broadcasts.keySet()) { 

				// 每进行一次for(每次往temp临时集合中存完数据 下次再使用前要把临时集合中的数据清空)
				tempSet.clear();
				// 当前这个key能够覆盖的地区 把地区放到areas中
				HashSet<String> areas = broadcasts.get(key);// 这个方法是通过key 取value 也就是key电台所能覆盖的所有地区
				tempSet.addAll(areas); // 把地区放到tempset中
				// 求出tempSet 和 allAreas 集合的交集, 交集会赋给 tempSet
				tempSet.retainAll(allAreas);
				// 如果当前这个集合包含的未覆盖地区的数量比maxKey指向的集合地区还多
				// 就需要重置maxKey 意思就是把地区最多的电台赋给maxkey
				// tempSet.size() >broadcasts.get(maxKey).size()) 体现出贪心算法的特点,每次都选择最优的
				// (tempSet.size() > 0 说明还未覆盖完所有地区 因为是和 allAreas还有交集
				if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {
					maxKey = key;
				}
			}
			
			if (maxKey != null) {
				selects.add(maxKey);// maxKey != null, 就应该将maxKey 加入selects
				allAreas.removeAll(broadcasts.get(maxKey));// 将maxKey指向的广播电台覆盖的地区,从 allAreas 去掉
			}

		}

		System.out.println("得到的选择结果是" + selects);// [K1,K2,K3,K5]

	}
}

/*Map集合遍历常用的方法: 获取所有的key ,存放在Set集合中,通过遍历key, 来遍历value
 * 
 * 1.先获取所有的key,所有的key是一个set集合 此处调用keySet方法,返回Set集合 Set<K> keySet() 其中K代表key的类型
 * 2.遍历key ,通过key获取value, Map.get(k)  得到value,然后遍历Set集合方法可以是迭代器或者foreach
 *  
 * 
 * while (allAreas.size() != 0) { 	 
		maxKey = null;	 
		for (String key : broadcasts.keySet()) { 	 
			tempSet.clear(); 
			HashSet<String> areas = broadcasts.get(key); 
			tempSet.addAll(areas);   
			tempSet.retainAll(allAreas);
			 
			if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {
				maxKey = key;
			}
		}
		
		if (maxKey != null) {
			selects.add(maxKey); 
			allAreas.removeAll(broadcasts.get(maxKey));
		}

	}

}*/

posted on 2022-03-19 15:35  精致猪猪侠  阅读(110)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3