首页 > 编程语言 >常见贪心算法类型

常见贪心算法类型

时间:2023-11-28 14:27:19浏览次数:38  
标签:20 哈夫曼 常见 算法 权值 区间 节点 贪心

备考建议

贪心思想是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,如果要得到整个问题的最优答案,那么每一步都要尽可能的得到最优的答案。

首先初赛必然无法考察贪心的证明。聚焦在贪心的经典题型,又因为贪心算法,方便与其他知识点关联,比如结构体排序后贪心,比如二分答案里做贪心,所以往往代码量和思维度都适合放在压轴题的位置。

解决初赛中的贪心问题,先要熟悉贪心的常见题型。

常见题型

最常见的贪心有两种。

  • 「我们将 XXX 按照某某顺序排序,然后按某种顺序(例如从小到大)选择。」。
  • 「我们每次都取 XXX 中最大/小的东西,并更新 XXX。」(有时「XXX 中最大/小的东西」可以优化,比如用优先队列维护)

第二种方式基本要用到“优先队列”这种数据结构,在CSP-J的组别里不可能出现,因为只需要准备第一种贪心。

傻瓜贪心

举个栗子 USACO DEC07 超级书架

题意是给定n个正整数和一个正整数k,问最少选择多少个正整数使得它们之和大于等于k。

很显然这类问题的求解,就是排序 + 统计。

哈夫曼树

哈夫曼树是一种二叉树,用于数据压缩。它的构建方式是通过对一个数据集中的元素进行频率统计,然后将频率较小的元素放在树的底部(远端),频率较大的元素放在树的顶部(近端),以此来减小数据的存储空间。

在哈夫曼树中,从根节点到某个叶子节点的路径上的编码,就是该叶子节点所表示字符的哈夫曼编码。

构造哈夫曼树

哈夫曼树的构建可以使用贪心算法来实现,时间复杂度为O(nlogn),其中n为数据集中元素的个数。

具体构建方式是,首先将所有元素按照出现频率从小到大排序,然后选取频率最小的两个元素作为左右子节点,将它们的频率相加作为父节点的频率,然后将父节点插入到排序后的元素列表中,重复上述步骤直到只剩下一个根节点为止。最后,从根节点开始递归遍历哈夫曼树,将每个叶子节点所表示的字符及其对应的哈夫曼编码存储起来。

假设有如下8个字符及对应的权值:

字符权值
A 2
B 3
C 7
D 10
E 11
F 13
G 14
H 20

我们可以按照以下步骤构造哈夫曼树:

  1. 将所有节点按照权值从小到大排序,得到 2,3,7,10,11,13,14,20。

  2. 选取权值最小的两个节点2和3,将它们合并为一个新节点,其权值为2+3=5。这个新节点代表的子树有2和3两个节点。

  3. 将得到的新节点5插入集合中,集合变为 5,7,10,11,13,14,20。

  4. 选取权值最小的两个节点5和7,将它们合并为一个新节点,其权值为5+7=12。这个新节点代表的子树有5和7两个节点。

  5. 将得到的新节点12插入集合中,集合变为 10,11,12,13,14,20。

  6. 选取权值最小的两个节点10和11,将它们合并为一个新节点,其权值为10+11=21。这个新节点代表的子树有10和11两个节点。

  7. 将得到的新节点21插入集合中,集合变为 12,13,14,20,21。

  8. 选取权值最小的两个节点12和13,将它们合并为一个新节点,其权值为12+13=25。这个新节点代表的子树有12和13两个节点。

  9. 将得到的新节点25插入集合中,集合变为 14,20,21,25。

  10. 选取权值最小的两个节点14和20,将它们合并为一个新节点,其权值为14+20=34。这个新节点代表的子树有14和20两个节点。

  11. 将得到的新节点34插入集合中,集合变为 21, 25, 34。

  12. 选取权值最小的两个节点21和25,将它们合并为一个新节点,其权值为21+25=46。这个新节点代表的子树有21和25两个节点。

  13. 将得到的新节点46插入集合中,集合变为 34, 46。

  14. 选取权值最小的两个节点34和46,将它们合并为一个新节点,其权值为34+46=80。这个新节点代表的子树有34和46两个节点。

  15. 哈夫曼树构建完成,根节点的权值为80,左子树的权值为34,右子树的权值为46。

下图为本例的哈夫曼树:

构建完哈夫曼树后,从哈夫曼树的根节点开始,遍历左子树的路径为0,遍历右子树的路径为1,则每个叶子节点对应的字符编码为从根节点到该叶子节点经过的路径上的0和1序列。注意,由于哈夫曼树是一棵前缀编码树,因此每个字符的编码不会是另一个字符编码的前缀。

本例中所有节点对应的编码如下:

字符权值编码
A 2 11000
B 3 11001
C 7 111
D 10 100
E 11 101
F 13 111
G 14 00
H 20 01

区间问题

最大不相交区间数量

举个栗子 leetcode 435 无重叠的子区间

给定一个区间的集合 A ,其中 A[i] = [starti​, endi​] 。返回 需要移除区间的最小数量,使剩余区间互不重叠。

区间分组

举个栗子 给定 N个闭区间 [ai​,bi​],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。 输出最小组数。

我们可以把所有开始时间和结束时间排序,遇到开始时间就把需要的教室加1,遇到结束时间就把需要的教室减1,在一系列需要的教室个数变化的过程中,峰值就是多同时进行的活动数,也是我们至少需要的教室数。

最小区间覆盖

给定 N个闭区间 [ai​,bi​]以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 −1。

分析: 第一步,将所有区间按照左端点从小到大进行排序

第二步,从前往后枚举每个区间,在所有能覆盖start的区间中,选择右端点的最大区间,然后将start更新成右端点的最大值

找拐点

求一个最长序列,使得该序列的任意三个相邻元素,中间的元素是三个中最大的,或者是最小的(最长波浪序列)

标签:20,哈夫曼,常见,算法,权值,区间,节点,贪心
From: https://www.cnblogs.com/luliusheng/p/17861856.html

相关文章

  • 排序算法之冒泡排序优化2
    一:概述对于冒泡排序的优化1中,右边的许多元素已经是有序的了,可是每一轮还是白白地比较多次了。这个问题地关键点在于对数列有序区地界定。按照现有的逻辑,有序区的长度和排序的轮数是相等的。例如第1轮排序过后的有序区长度是1,第2轮排序过后的有序长度是2....实际上,数列真正的有序区......
  • 期望最大化(EM)算法:从理论到实战全解析
    本文深入探讨了期望最大化(EM)算法的原理、数学基础和应用。通过详尽的定义和具体例子,文章阐释了EM算法在高斯混合模型(GMM)中的应用,并通过Python和PyTorch代码实现进行了实战演示。关注TechLead,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济......
  • 期望最大化(EM)算法:从理论到实战全解析
    本文深入探讨了期望最大化(EM)算法的原理、数学基础和应用。通过详尽的定义和具体例子,文章阐释了EM算法在高斯混合模型(GMM)中的应用,并通过Python和PyTorch代码实现进行了实战演示。关注TechLead,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济......
  • 算法分析-寻找假币题
    一.题目需求你手里有70枚重量相等的真金硬币,但你知道其中有一枚是假币,比其他金币轻。你有一个平衡秤,你可以一次在两边放上任意数量的硬币,它会告诉你两边是否重量相同,或者如果不相同,哪边更轻。问题:请概述一个寻找假币的算法。你需要称量多少次?怎么使得称量次数最少?二、算法思想1......
  • 集合框架(一) Java中Map的常见方法的使用及循环的五种方式
    Map是Java中的一种集合,它是一种键值对的映射表,可以根据键快速获取对应的值。@[toc]##1.常见使用方式以下是Java中Map的常见方法使用示例及运行结果:###1.1存储键值对使用put()方法向Map中添加键值对:```javaMap<String,Integer>map=newHashMap<>();map.put("apple",10......
  • 文心一言 VS 讯飞星火 VS chatgpt (145)-- 算法导论12.1 5题
    五、用go语言,因为在基于比较的排序模型中,完成n个元素的排序,其最坏情况下需要Ω(nlgn)时间。试证明:任何基于比较的算法从n个元素的任意序列中构造一棵二又搜索树,其最坏情况下需要Ω(nlgn)的时间。我个人喜欢灵小智。文心一言:首先,我们要明白二叉搜索树(BST)的性质:每个节点......
  • 【动态规划】【贪心】 [POI2011] DYN-Dynamite
    这俩东西是怎么结合到一起的?题目描述给一棵树,树上有一些关键节点,要求你选\(m\)个点,第\(i\)个关键节点到这些点中每个点距离的最小值记为\(dis_i\),记这全部\(dis\)的最大值为\(K\),现在要使\(K\)最小,求这个\(K\)。\(1\leqn,m\leq3\times10^5\)。算法描述让最......
  • matplotlib之常见图像种类
    Matplotlib是一个用于绘制图表和数据可视化的Python库。它支持多种不同类型的图形,以满足各种数据可视化需求。以下是一些Matplotlib支持的主要图形种类:折线图(LinePlot):用于显示数据随时间或其他连续变量的变化趋势。plt.plot() 函数用于创建折线图。 散点图(S......
  • 差分算法总结
    差分是前缀和的逆运算一维差分对于a1,a2,…,an,构造b1,b2,…,bn,使得ai= b1+ b2 + …+bi。此时,b数组成为a数组的差分,a数组称为b数组的前缀和。题目链接:https://www.acwing.com/problem/content/799/代码模版:1#include<iostream>23usingnamespacestd;45co......
  • O(nlogn)排序算法
    排序算法介绍常见时间复杂度为\(O(nlogn)\)的排序算法1.快速排序分治思想#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+10;inta[N];voidquick_sort(intl,intr){if(l>=r)return;intx=a[l+r>>1],i=l-1,j=r+1;......