#04贪心法

news2024/7/4 3:47:14

要点:

贪心法的基本思想、基本要素与求解步骤;

贪心法的应用。

难点:

贪心法的最优子结构性质与贪心选择性质。


贪心法的基本思想

每个阶段的决策一旦做出就不可更改。不允许回溯。

并不从整体最优考虑,所作出的选择只是在某种意义上的局部最优选择,并希望该局部最优选择可以导致一个全局最优解。

但对许多问题(如单源最短路经问题、最小生成树问题等)能产生整体最优解。

即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

贪心法的条件判断

贪心选择性质【归纳法证明】 最优子结构性质【反证法证明】

 贪心法的解决步骤

分解: 将原问题分解为若干个相互独立的阶段。

解决: 对于每个阶段依据贪心策略进行贪心选择,求出局部的最优解。

合并: 将各个阶段的解合并为原问题的一个可行解。


会场安排问题

设有n个会议的集合C={1,2,…,n},其中每个会议都要求使用同一个资源(如会议室),而在同一时间内只能有一个会议使用该资源。

每个会议i都有要求使用该资源的起始时间bi和结束时间ei,且bi < ei 。如果选择了会议i使用会议室,则其在半开区间[bi, ei)内占用该资源。

贪心策略选择

选择最早开始时间且不与已安排会议重叠的会议: 但如果会议的使用时间无限长,如此选择策略就只能安排1个会议来使用资源。不可行。

选择使用时间最短且不与已安排会议重叠的会议: 但如果会议的开始时间最晚,如此选择策略也就只能安排1个会议来使用资源。不可行。

选择最早结束时间且不与已安排会议重叠的会议: 如果选择开始时间最早且使用时间最短的会议,较为理想。而此即结束时间最早的会议。可行。

求解步骤

①初始化,并按会议结束时间非减序排序【结束时间从早到晚】

开始时间存入数组B,结束时间存入数组F中; 按照结束时间的非减序排序,B需做相应调整; 集合A存储解。如果会议i在集合A中,当且仅当其被选中。

②根据贪心策略,做第一次贪心选择。

首令A[1] = 1;

③依次扫描每一个会议,直至所有会议检查完毕。

如果会议i的开始时间不小于最后一个选入A中的会议的结束时间,则将会议i加入A中; 否则,放弃并继续检查下一个会议与A中会议的相容性。

//基于贪心法求解会场安排问题的伪代码如下:
GREEDY-ACTIVITY-SELECTOR(B,E) //B,E为会以的开始时间和结束时间
  SORT-ASC-BY-F(B,E) //对E按减序排序并同时调整S
  n = B.length
  A = {1} //首先选择会议1
  k = 1 //已被选择会议集合中最晚结束的会议
  for m = 2 to n
    if B[m] >= E[k] //会议m的开始时间不小于会议k的结束时间
	    then A = A ∪ {m} //将会议m加入到集合A中
           k = m //此时集合A中最晚结束的会议为m
    return A

贪心选择性质【归纳法证明】 最优子结构性质【反证法证明】 略~

 (a) 按照会议结束时间非减序排序(如采用归并);

(b) 逐个检查剩下会议与已选择会议的相容性。

时间复杂性: (a):O(nlogn),(b):O(n)。->   O(nlogn)

空间复杂性: (a):O(n),(b):O(1)。->    O(n)


哈夫曼 (Huffman) 编码

怎样保证上述编码树所得到的编码总长度(亦即编码树的带权路径长度)最小?

以字符的使用频率作为结点的权构建哈夫曼树,核心思想是让权值较大的叶子离根更近(即频率高的字符编码短)。

贪心策略:

每次从树的集合(初始为n棵平凡树)中取出权值最小的两棵树作为左、右子树,构造一棵新树。新树的根结点的权值为其左右孩子结点权值之和,并将新树插入到树的集合中。

迭代地执行上述步骤,直至树的集合中只剩下一棵树为止,即得到哈夫曼编码树。

求解步骤:

①确定合适的数据结构;

②初始化。

构造n棵结点为n个字符的单结点树集合F={T1,T2,…, Tn},每棵树中只有一个带权的根结点,权值为该字符的使用频率;

③如F中只剩下一棵树,则哈夫曼树构造成功,转步骤6;否则,从集合F中取出权值最小的两棵树Ti和Tj,将它们合并成一棵新树Zk,新树以Ti为左儿子, Tj为右儿子(反之也可以)。新树Zk的根结点的权值为Ti与Tj的权值之和;

④从集合F中删去Ti、Tj,集合F加入Zk;

⑤重复步骤3和4;

⑥从叶子结点到根结点逆向求出每个字符的哈夫曼编码(约定左分支表示字符“0”,右分支表示字符“1”)。则从根结点到叶子结点路径上的分支字符组成的字符串即为叶子字符的哈夫曼编码。 算法结束。

基于贪心法求解哈夫曼编码问题的伪代码如下:
HUFFMAN(C) //C为具有n个待编码字符的集合
  n = C.length
  Q = C //Q为以freq为关键字的最小优先队列,存放已组合的二叉树
  for i = 1 to n-1
    z  allocate a new node //构建一个以z为根的一个新二叉树
    x = EXTRACT-MIN(Q) //从Q中出列一棵树x
	  z.left = x //将树x作为z的左子树
    y = EXTRACT-MIN(Q) //从Q中出列一棵树y
    z.right = y //将树y作为z的右子树
    z.freq = x.freq + y.freq //以x和y的freq作为z的freq
    INSERT(Q, z) //将构建的新树插入到Q中
  return EXTRACT-MIN(Q)

字符对应的哈夫曼编码:自叶子结点到根反向遍历

贪心选择性质【证明】 最优子结构性质【证明】 略~

时空复杂性分析 

未采用特殊数据结构时算法的复杂性:

时间复杂性:O(n2) 空间复杂性:O(n)(视排序是否为in-place而定)

采用最小二叉堆时算法的复杂性:

时间复杂性:O(nlogn) 空间复杂性:O(n)


单源最短路径 (SSSP)

两个结点u和v之间的最短带权路径长度(u, v):               

单源最短路径问题要求:计算源点s到其他各个结点v的最短路径(及其)长度δ(s, v)。

狄克斯特拉算法 Dijkstra

迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止

贪心选择性质【证明】 最优子结构性质【证明】 略~

时空复杂性分析 

时间复杂性:

EXTRACT-MIN()的时间复杂性为O(logn);

二重循环的执行次数为(n-1)+(n-2)+…+1 = n(n-1)/2,即时间复杂性为O(n^2)。

所以,该算法的时间复杂性为O(n^2)

空间复杂性:

堆排序为in-place排序。辅助变量O(n);

所以,该算法的空间复杂性为O(n)。 

详细图解过程: 

图论:Dijkstra算法——最详细的分析,图文并茂,一次看懂!-CSDN博客


最小生成树 MST

设G=(V, E)是无向连通带权图。E中每条边(v, w)的权为c[v][w]。最小生成树:在G的所有生成树中,耗费最小的生成树。

应用:

1)在设计通信网络时,用图的顶点表示城市,用边(v,w)的权c[v][w]表示建立城市v和城市w之间的通信线路所需的费用,则最小生成树就给出了建立通信网络的最经济的方案

2) 城市之间的公路网等都是最小生成树的实际应用例子。

Prim算法

算法实现方法:

  1. 将连通网中的所有顶点分为两类(假设为 A 类和 B 类)。初始状态下,所有顶点位于 B 类;
  2. 选择任意一个顶点,将其从 B 类移动到 A 类;
  3. 从 B 类的所有顶点出发,找出一条连接着 A 类中的某个顶点且权值最小的边,将此边连接着的 A 类中的顶点移动到 B 类;
  4. 重复执行第 3  步,直至 B 类中的所有顶点全部移动到 A 类,恰好可以找到 N-1 条边。
// Prim算法的伪代码:
MST-PRIM(G, w, r) //r为根结点
  for each u∈G.V //初始化
    u.key = ∞ //u.key为连接u和树中结点所有边中最小边的权重
    u.p = NIL //u.p为结点u的父结点
  r.key = 0
  Q = G.V //极小优先队列(v.key)。后述的U=V-Q,V-U=Q
  while Q ≠ Φ
    u = EXTRACT-MIN(Q)
    for each v∈ (G.Adj[u] ∩ Q)
      if(w(u, v) < v.key
        v.p = u
        v.key = w(u, v) //DECREASE-KEY
时空复杂性 

时间复杂性:

使用数组,则为O(|V|^2),这里V为图中结点。

使用二叉堆,则O(|V|log|V|)。

空间复杂性:

O(|V|)。

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​prim算法(普里姆算法)详解 (biancheng.net)


Kruskal算法

设G=(V,E)是具有n个结点的无向连通带权图,U是V。的一个非空子集。最小生成树的一个很重要的性质: 若(u, v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u,v)的最小生成树。

Kruskal算法的关键是怎样判断加入某条边后图T会不会出现回路;

Kruskal算法的求解步骤:

① 初始化。将图G的边集E中的所有边按权从小到大排序,边集TE={},把每个顶点都初始化为一个孤立的分支,即一个顶点对应一个集合;

② 寻找权值最小的边。在E中寻找,得边(i,j);

③ 如不形成回路,则将边(i,j)加入TE。如结点i和j位于两个不同连通分支,则将边(i,j)加入边集TE,并执合并操作将两个连通分支进行合并;

④将新加入的边从E中删除。即E=E-{(i,j)};

⑤ 判断算法是否结束。如连通分支数目不为1,转步骤2;否则,算法结束,生成最小生成树T。 

//Kruskal算法的伪代码:
MST-KRUSKAL(G, w)
  A = Φ //最优解。边的集合
  for each v∈G.V
    MAKE-SET(v) //创建|V|棵仅含一个结点的树
  sort the edges of G.E into non-decreasing order by weight w
  for each edge(u, v)∈G.E //in nondecreasing order by weight w 
    if(FIND-SET(v) ≠ FIND-SET(u)) //v和u不属于同一棵树
      A = A ∪{(u, v)} //将边(u,v)加入到A中
      UNION(u, v) //基于边(u,v)合并两棵树
  return A

贪心选择性质【证明】 最优子结构性质【证明】 略~

Kruskal算法~问题1:选取权值最小的边的同时,要判断加入该条边后树中是否出现回路;

                     问题2:不同的连通分支如何进行合并。

时空复杂性

时间复杂性: O(|E|log|E|) 或 O(|E||V|) 。E为边,V为节点。

空间复杂性: O(|E|)。

【算法】最小生成树——Prim和Kruskal算法_kruskal最小生成树图解-CSDN博客
两种算法的比较

Kruskal适用于稀疏图,而Prim适用于稠密图;

从时间上讲,Prim算法的时间复杂度为O(V2)或O(ElogV),Kruskal算法的时间复杂度为O(ElogV)。 从空间上讲,显然在Prim算法中,只需要很小的空间就可以完成算法,因为每一次都是从个别点开始出发进行扫描的,而且每一次扫描也只扫描与当前顶点集对应的边。但在Kruskal算法中,因为时刻都得知道当前边集中权值最小的边在哪里,这就需要对所有的边进行排序,对于很大的图而言,Kruskal算法需要占用比Prim算法大得多的空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1861947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频素材网站哪个好用?好用的做短视频素材下载网站分享

你是否正面临着为短视频寻找完美素材的困扰&#xff1f;是否对网络上那些雷同的素材网站感到厌烦了&#xff1f;今天&#xff0c;我将为大家推荐几个优秀的海外视频素材网站&#xff0c;这些隐藏的宝藏网站定能让你的作品焕发新光彩&#xff01; 蛙学素材网——您的创作好帮手…

希望数学少年俱乐部精品课学生用书-四年级

PDF版本链接链接&#xff1a;https://pan.baidu.com/s/1t6prtG9sd-1mYsnCUz-mKQ 提取码&#xff1a;0548 --来自百度网盘超级会员V7的分享

《编译原理》阅读笔记:p19-p24

《编译原理》学习第 4 天&#xff0c;p19-p24总结&#xff0c;总计 5 页。 一、技术总结 1.grouping of phases 这里谈到分组(group)&#xff0c;那么就会有一个疑问&#xff0c;分组的依据是什么&#xff1f;即根据什么来分组。 (1) front end & back end 编译器包含…

办公效率神器:ONLYOFFICE 的配置和使用

1.认识 ONLYOFFICE ONLYOFFICE 是一款免费开源的协同办公软件套件&#xff0c;支持多种文件格式&#xff0c;包括PDF、Word、Excel、PowerPoint等。它提供了文档编辑、表格处理、演示制作等功能&#xff0c;并可以与其他应用程序和平台集成&#xff0c;功能亮点特点如下&#…

【unity笔记】六、UI实现下拉列表切换视角

具体步骤如下 1. 创建UI下拉列表&#xff1a; 在Unity场景中右键点击并选择UI -> 下拉列表 来创建一个新的下拉列表。 2. 添加摄像机选项&#xff1a; 在Dropdown的Options属性中添加新的选项&#xff0c;通过点击按钮来添加选项&#xff0c;并为每个选项设置一个显示名…

【大数据】—谁是世界上最富的人?

引言 在2024年&#xff0c;全球财富的分布再次成为公众和经济学家关注的焦点。随着经济的波动和新兴市场的崛起&#xff0c;亿万富翁的名单也在不断变化。本文将深入探讨这一现象&#xff0c;通过最新的数据可视化分析&#xff0c;揭示世界上最富有的人在2024年的财富状况和趋…

成都百洲文化传媒有限公司助力电商品牌乘风破浪

在当今数字化时代&#xff0c;电商行业风起云涌&#xff0c;竞争异常激烈。成都百洲文化传媒有限公司凭借其对电商行业的深刻理解与实战经验&#xff0c;已然成为行业中的佼佼者。公司专注于电商服务领域&#xff0c;通过创新的营销模式和精准的市场策略&#xff0c;助力众多品…

#03动态规划

要点&#xff1a; 动态规划方法与贪心法、分治法的异同&#xff1b; 动态规划方法的基本要素与求解步骤&#xff1b; 动态规划方法的应用。 难点&#xff1a; 如何根据问题的最优子结构性质构造构造动态规划方法中的递归公式或动态规划方程。 动态规划的基本思想 动态规…

使用Servlet开发javaweb,请求常见错误详解及其解决办法【404、405、500】

Servlet报错的情况多种多样&#xff0c;涵盖了配置错误、代码逻辑错误、资源未找到、权限问题等多个方面。以下是一些常见的Servlet报错情况及其可能的原因和解决方法&#xff1a; 404 Not Found: 错误原因图示&#xff1a; URL映射 发送请求&#xff0c;出现404错误 原因: 请…

excel隐藏的部分内容如何显示出来?3个方法帮助你!

excel隐藏的部分如何显示出来&#xff1f;你是否曾经在Excel中遇到过某些单元格被隐藏&#xff0c;或者某些数据在编辑时突然消失&#xff0c;让你感到困惑和无助&#xff1f;不要担心&#xff0c;今天我将向你揭示如何解决这些问题&#xff0c;让你轻松显示隐藏的部分。 方法1…

神经网路学习7-线性模型

一个最简单的线性模型&#xff0c;w是权重&#xff0c;一般来说会取随机值&#xff0c;然后不断学习直到与预期相同 如此以此取每个值与真实值的差值&#xff0c;即评估误差 即找一个合适的权重w&#xff0c;使得平均误差最小 上面的是针对单个样本的&#xff0c;后面的是对…

onnx模型修改:去掉Dropout层

文章目录 尝试1&#xff1a;强行设置dropout层train mode为False尝试2&#xff1a;找到onnx模型中的dropout, train mode设置为False尝试3&#xff1a;直接删除dropout层&#xff0c;连接其输入输出结语 最近训练模型使用了tinyvit&#xff0c;性能挺强的&#xff1a; 但是导出…

Posix消息队列使用总结

Posix在线文档&#xff1a; The Single UNIX Specification, Version 2 (opengroup.org) Linux系统中提供了两种不同接口的消息队列&#xff1a; POSIX消息队列。POSIX为可移植的操作系统接口。System V消息队列。System V 是 AT&T 的第一个商业UNIX版本(UNIX System III)的…

【Mac】iTerm for mac(终端工具)软件介绍及安装教程

软件介绍 iTerm 是 macOS 上一个非常受欢迎的终端仿真器&#xff0c;提供了比默认的 Terminal 应用更多的功能和定制选项。它是一款开源软件&#xff0c;主要用于命令行界面的操作和开发者工具。 主要特点和功能&#xff1a; 分页和标签&#xff1a; iTerm 允许用户在单个窗…

Spring Boot项目的两种发布方式

5.1.方式1&#xff1a;通过jar包发布 步骤1&#xff1a;在pom中添加一个SpringBoot的构建的插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><!--自动检测项目中的 main 函数--><artifactId>spring-boot…

开发一款直播APP完整指南

直播是一种强大的营销工具&#xff0c;可以让企业与观众进行真实的互动。 根据Grand View Research发布的预测&#xff0c;直播行业规模将从 2021 年的 700 亿美元增长到 2028 年的近 2240 亿美元&#xff0c;七年内增长三倍。 区块链技术和人工智能等技术进步将在未来几年提…

mybatis-plus 实体中空字段更新不上

FieldStrategy 是一个枚举类型&#xff0c;它定义了字段的几种策略&#xff1a; IGNORED&#xff1a;忽略判断&#xff0c;所有字段都进行更新操作 NOT_NULL&#xff1a;非 NULL 判断&#xff08;默认策略&#xff09;&#xff0c;字段非 NULL 才进行更新 NOT_EMPTY&#xff…

数据结构与算法—空间复杂度详解与示例(C#,C++)

文章目录 1. 数据结构概述2. 空间复杂度的定义及影响因素3. 空间复杂度的区分常数空间复杂度&#xff08;O(1)&#xff09;线性空间复杂度&#xff08;O(n)&#xff09;其他空间复杂度 4. 几种典型数据结构的优缺点分析数组&#xff08;Array&#xff09;链表&#xff08;Linke…

专业解析U盘数据恢复:方法、方案与常见问答

一、U盘数据恢复概述 在信息化社会&#xff0c;U盘作为一种便捷的数据存储介质&#xff0c;广泛应用于各种场合。然而&#xff0c;由于其体积小、易携带的特点&#xff0c;U盘数据丢失的风险也随之增加。U盘数据恢复&#xff0c;即是指通过技术手段&#xff0c;将因各种原因导…

【Spine学习16】之 人物面部绑定

1、创建头部骨骼 一根头骨 以头骨为父结点创建一个面部控制器face-holder 2、创建头发和face面部控制结点的变换约束 左右头发的约束指向为face结点 3、设定后发的变换约束&#xff0c;约束指向为face结点&#xff0c;反方向移动 设置参数为-100 同理&#xff0c;耳朵也依…