20天拿下华为OD笔试之【DP/贪心】2023B-观看文艺汇演【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 【DP/贪心】2023B-观看文艺汇演
  • 题目描述与示例
    • 输入
    • 输出
    • 示例一
      • 输入
      • 输出
      • 说明
    • 示例二
      • 输入
      • 输出
      • 说明
    • 示例三
      • 输入
      • 输出
  • 解题思路
    • 原始数据处理
    • 贪心思想求解问题
    • 动态规划求解问题
  • 代码
    • 解法一:贪心
      • 时空复杂度
    • 解法二:DP
      • 时空复杂度
  • 华为OD算法冲刺训练

【DP/贪心】2023B-观看文艺汇演

题目描述与示例

某公园将举行多场文艺表演,很多演出都是同时进行,一个人只能同时观看一场演出,且不能迟到早退,由于演出分布在不同的演出场地,所以连续观看的演出最少有 15 分钟的时间间隔,小明是一个狂热的文艺迷,想观看尽可能多的演出。现给出演出时间表,请帮小明计算他最多能观看几场演出。

输入

第一行为一个数 N,表示演出场数,1 <= N <= 1000

接下来 N 行,每行两个空格分割的整数,第一个整数 T 表示演出的开始时间,第二个整数 L 表示演出的结束时间,TL 的单位为分钟,0 <= T <= 1440, 0 < L <= 100

输出

最多能观看的演出场数。

示例一

输入

2
720 120
840 120

输出

1

说明

第一场演出开始时间是第 720 分钟,经过 120 分钟演出结束,即第 840 分钟结束,此时还需要 15 分钟的间隔时间,即要等到第 855 分钟才可以看下一场演出,故来不及看第二场在第 840 分钟开始的演出。最多只能看 1 场演出。

示例二

输入

2
20 60
100 60

输出

2

说明

第一场演出开始时间是第 20 分钟,经过 60 分钟演出结束,即第 80 分钟结束,此时还需要 15 分钟的间隔时间,即要等到第 95 分钟才可以看下一场演出,第二场演出在第 100 分钟开始的演出,赶得上观看第二场演出。最多可以观看 2 场演出。

示例三

输入

4
10 20
100 20
150 60
80 40

输出

3

解题思路

注意,本题和 LC435. 无重叠区间几乎完全一致。

原始数据处理

我们可以储存每一场演出的开始和结束时间,即按照 [start, end] 的方式进行储存,储存在列表 intervals 中。由于题目要求每间隔 15 分钟才能够看下一场演出,所以我们可以把每一场演出的结束时间再加上 15 分钟,这样题目就转变为:考虑所有不重叠的 [start, end] 区间的最大数目。处理输入的代码如下

N = int(input())
intervals = list()
for _ in range(N):start, during = map(int, input().split())end = start + during + 15intervals.append((start, end))

贪心思想求解问题

为了方便我们贪心地思考问题,我们先按照开始时间 start 从小到大对间隔列表 intervals 进行排序。然后我们考虑相邻的两场演出,[start1, end1][start2, end2],由于 intervals 已经排序,必然存在 start1 <= start2 成立,故这两场演出之间的关系存只有以下三种可能性

  1. start1 < end1 <= start2 < end2,即演出 2 的开始时间在演出 1 的结束时间之后。故看完演出 1,可以继续看演出 2
  2. start1 <= start2 <= end1 <= end2,即演出 2 的开始时间在演出 1 的结束时间之前,但演出 2 的结束时间在演出 1 的结束时间之后。故看完演出 1 之后,没办法观看演出 2
  3. start1 <= start2 <= end2 <= end1,即演出 2 的开始时间和结束时间均在演出 1 的结束时间之前。故看完演出 1 之后,没办法观看演出 2。为了尽可能多地看更多的演出,选择演出 2 来观看会比选择演出 1 更好,因为演出 2 的结束时间更早,有充裕的时间去观看后续的演出。

理解了相邻两场演出的三种可能性之后,我们发现解决问题的关键实际上在于考虑演出 1 的结束时间 end1 和演出 2 的间隔 [start2, end2] 之间的关系:

  1. end1[start2, end2] 之前
  2. end1[start2, end2] 之间
  3. end1[start2, end2] 之后

由于我们需要遍历排序后的间隔列表 intervals 中的每一个间隔 [start, end],因此可以维护变量 pre_end,表示上一场演出的结束时间。初始化 pre_end = -inf,表示第一场演出始终可以观看。

考虑当前间隔 [start, end] 和上一场演出结束时间 pre_end 之间的关系,我们可以得到以下逻辑:

  1. pre_end[start, end] 之前,我们可以选择当前的演出 [start, end] 进行观看

    • 能观看的演出场次 ans += 1
    • 由于选择了 [start, end] 进行观看,下一场演出的观看时间应该由当前的 end 决定,即对于下一场演出而言,当前结束时间 end 是上一场演出的结束时间,故更新 pre_end = end
  2. pre_end[start, end] 之间,我们不能选择当前的演出 [start, end] 进行观看

    • 由于 pre_end ≤ end,因此我们保留之前的 pre_end,作为判断下一场演出是否能观看的依据。故无需做任何事情。
  3. pre_end[start, end] 之后,我们不能选择当前的演出 [start, end] 进行观看

    • 由于 pre_end > end,选择 end 作为判断下一场演出是否能观看的依据是更佳的选择,即我们不去选择观看 pre_end 所对应的之前某场演出,而选择观看当前的演出 [start, end],这样的选择有利于后面留出充裕的时间来尽可能地观看更多演出,故更新 pre_end = end

整理上述逻辑后,代码为

for start, end in intervals:if start >= pre_end:ans += 1pre_end = endelif start < pre_end <= end:continueelif pre_end > end:pre_end = end

动态规划求解问题

实际上,当我们对间隔列表 intervals 排序之后,我们也可以把这个问题当作经典的 LIS 问题(LC300. 最长递增子序列)进行处理。

譬如对于上述例子,我们所选的演出应该为演出 145

换句话说,我们需要找到尽可能多的演出区间,所有演出区间均需要满足 start ≥ pre_end,其中 start 为第 i 个区间的开始时间,pre_end 为上一个区间即第第 i-1 个区间的结束时间。这是一个非常自然的 LIS 问题,故也可以用 dp 来解决问题。

我们考虑动态规划三部曲:

  1. dp数组的含义是什么?
  • dp 数组是一个长度为 n 的一维列表,dp[i] 表示包含了第 i 场演出 intervals[i] 的最长无重叠演出数目。
  1. 动态转移方程是什么?
  • 包含了第 i 场演出 intervals[i] 的最长无重叠演出数目,由前面的 i-1 场演出中(用索引 j 表示),结束时间 intervals[j][1] 小于当前演出开始时间 intervals[i][0]dp[j] 最大的那场演出决定。
for i in range(1, N):temp = 0for j in range(i):if intervals[j][1] <= intervals[i][0]:temp = max(dp[j], temp)dp[i] = temp + 1
  1. dp数组如何初始化?
  • 包含第 1 场演出的最长无重叠演出数目为 1
dp[0] = 1

代码

解法一:贪心

# 题目:2023B-观看文艺汇演
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:贪心
# 代码看不懂的地方,请直接在群上提问from math import inf# 输入演出的数目
N = int(input())# 初始化间隔列表
intervals = list()
for _ in range(N):start, during = map(int, input().split())# 对于每一个结束时间都+15后再储存,方便后续进行比较end = start + during + 15intervals.append((start, end))# 对intervals进行排序
intervals.sort()
ans = 0# 初始化【上个区间结束时间】为pre_end = -inf
pre_end = -inf# 遍历所有区间的起始时间和结束时间
for start, end in intervals:# 如果【当前起始时间】大于等于【上次结束时间】# 可以选择【当前区间】进行观看,接在【上个区间】后面# 同时 pre_end 应该修改为【当前结束时间】# 作为下一个区间的【上次结束时间】if start >= pre_end:ans += 1pre_end = end# 如果【上次结束时间】正好落在【当前区间】内# 则不能选择【当前区间】进行观看,保留【上个区间】# 无需做任何事情elif start < pre_end <= end:continue# 如果【上次结束时间】大于【当前结束时间】# 则应该选择【当前区间】进行观看,而不应该选择【上个区间】# 故 pre_end 应该修改为【当前结束时间】# 作为下一个区间的【上次结束时间】elif pre_end > end:pre_end = endprint(ans)

时空复杂度

时间复杂度:O(NlogN)。排序时间复杂度。

空间复杂度:O(1)。仅需要用到若干常数变量。

解法二:DP

# 题目:2023B-观看文艺汇演
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:dp(LIS问题)
# 代码看不懂的地方,请直接在群上提问# 输入演出的数目
N = int(input())# 初始化间隔列表
intervals = list()
for _ in range(N):start, during = map(int, input().split())# 对于每一个结束时间都+15后再储存,方便后续进行比较end = start + during + 15intervals.append((start, end))# 对intervals进行排序
intervals.sort()
ans = 0# 初始化长度为N的dp数组
dp = N * [0]
# 包含第1场演出的最长无重叠演出数目为1
dp[0] = 1# 遍历所有演出
for i in range(1, N):# 初始化变量temp,用于找到前面的i-1场演出中,最长无重叠的演出场次temp = 0# 对于每一场演出i,遍历其前面的i-1场演出for j in range(i):# 如果演出j的结束时间,小于等于当前演出i的开始时间if intervals[j][1] <= intervals[i][0]:# 则更新temptemp = max(dp[j], temp)# 结束上述循环后,还需要考虑本场演出本身dp[i] = temp + 1# dp数组中的最大值,即为最长无重叠的演出场次
# 也就是能够观看的最多的演出场次
print(max(dp))

时空复杂度

时间复杂度:O(N^2)。dp 过程需要进行双重循环。

空间复杂度:O(N)。dp 数组所占空间。

华为OD算法冲刺训练

  • 华为OD算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 30+天陪伴式学习,20+直播课时,300+动画图解视频,200+LeetCode经典题,100+华为OD真题,还有简历修改与模拟面试将为你解锁

  • 可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

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

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

相关文章

Frida hook android 应用程序

Frida hook android 应用程序 之前已经讲过了frida的安装和使用&#xff0c;本篇文章主要讲下怎么hook android 的应用程序。 1&#xff1a;编写hook脚本 如下test.js Java.perform(function () {var WelcomeActivity Java.use(com.tencent.mm.plugin.account.ui.WelcomeA…

五年程序员兼职接单的肺腑之言

不知不觉我已经参加工作&#xff0c;当一个程序员五年了&#xff0c;从一个职场菜鸟逐渐变成老油条&#xff0c;个中辛酸只有自己知道。这五年做过各种兼职接单&#xff0c;踩过不少坑&#xff0c;今天就把我在程序员接单上的一些心得体会分享给大家&#xff0c;希望能对兼职接…

【开题报告】基于uni-app的恋爱打卡app的设计与实现

1.选题背景 如今&#xff0c;随着移动互联网的普及和人们对生活品质的追求&#xff0c;恋爱已经成为了许多人关注的焦点。然而&#xff0c;在恋爱过程中&#xff0c;由于种种原因&#xff0c;往往会忽略掉一些重要的时刻和细节&#xff0c;导致感情降温甚至破裂。因此&#xf…

poetry执行报错 Reason: tried: ‘/opt/homebrew/Cellar/python@x.x

报错如下&#xff1a; ➜ poetry shell ➜ poetry run uvicorn main:app --reload --port 7000 dyld[42259]: Library not loaded: /opt/homebrew/Cellar/python3.9/3.9.13_1/Frameworks/Python.framework/Versions/3.9/PythonReferenced from: <63F55A2A-2EB4-35B8-9170-9…

Redis--字符串

基础概念 字符串、数字&#xff0c;都会转化为字符串来进行存储 以二进制的方式存储在内存中 key的命名规范 key不宜过长&#xff0c;消耗内存&#xff0c;且在数据查找的这类键值的计算成本高&#xff08;通过hash计算来查找&#xff09;不宜过短&#xff0c;可读性查值一…

设计模式-命令模式-笔记

“行为变化”模式 在组件的构建过程中&#xff0c;组件行为的变化经常导致组件本身剧烈的变化。“行为变化”模式组件的行为和组件本身进行解耦&#xff0c;从而支持组件行为的变化&#xff0c;实现两者之间的松耦合。 经典模式&#xff1a;Command、Visitor 动机&#xff0…

C# - Opencv应用(2) 之矩阵Mat使用[矩阵创建、图像显示、像素读取与赋值]

C# - Opencv应用&#xff08;2&#xff09; 之矩阵Mat使用[矩阵创建、图像显示、像素读取与赋值] 矩阵创建图像显示与保存像素读取与赋值新建sample02项目&#xff0c;配置opencv4相关包&#xff0c;新建.cs进行测试 1.矩阵创建 //创建空白矩阵 var dst new Mat()//创建并赋…

Continuity” of stochastic integral wrt Brownian motion

See https://imathworks.com/math/math-continuity-of-stochastic-integral-wrt-brownian-motion/

【开源】基于Vue.js的教学过程管理系统

项目编号&#xff1a; S 054 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S054&#xff0c;文末获取源码。} 项目编号&#xff1a;S054&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 教师端2.2 学生端2.3 微信小程序端2…

基于Vue+SpringBoot的桃花峪滑雪场租赁系统

项目编号&#xff1a; S 036 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S036&#xff0c;文末获取源码。} 项目编号&#xff1a;S036&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设…

什么是Jmeter ?Jmeter使用的原理步骤是什么?

1.1 什么是 JMeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于 Web 应用测试&#xff0c;但后来扩展到其他测试领域。 它可以用于测试静态和动态资源&#xff0c;例如静态文件、Java 小服务程序、CGI 脚本…

力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)

Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff…

毕业论文GPT说:

作为一个计算机专业的大四学生&#xff0c;学过英语&#xff0c;微积分&#xff0c;离散数学&#xff0c;概率论与数理统计&#xff0c;线性代数&#xff0c;具体数学&#xff0c;数论&#xff0c;C语言&#xff0c;汇编语言&#xff0c;在网格机算、数据科学、机器学习与智能工…

媲美有线操作,支持4KHz响应和无线充电的游戏鼠标,雷柏VT3S上手

对于无线鼠标来说&#xff0c;操作延迟和精度对游戏操作影响很大&#xff0c;常见的游戏鼠标至少都有1KHz的回报率&#xff0c;而雷柏今年已经出了很多支持4KHz回报的鼠标了&#xff0c;像是我现在用的这款VT3S游戏鼠标&#xff0c;就搭载了旗舰级的原相3395引擎&#xff0c;支…

ORA-02291: 违反完整约束条件 (*) - 未找到父项关键字

在用Oracle中经常碰到有这种情况&#xff0c;ORA-02291: 违反完整约束条件 (*) - 未找到父项关键字 总体说说可能出现的原因&#xff1a; 情况场景&#xff1a; 表A中有个字段是外键&#xff0c;关联了表B中的某字段&#xff0c;再往表A插入数据时&#xff0c;会出现这种情况…

fractional Brownian Motion driven stochastic integrals

See https://mathoverflow.net/questions/304366/fractional-brownian-motion-driven-stochastic-integrals

2023年G3锅炉水处理证考试题库及G3锅炉水处理试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年G3锅炉水处理证考试题库及G3锅炉水处理试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机…

初学Redis(Redis的启动以及字符串String)

首先使用在Windows PowerShell中输入指令来启动Redis&#xff1a; redis-server.exe 然后通过指令连接Redis&#xff1a; redis-cli 上图的127.0.0.1是计算机的回送地址 &#xff0c;6379是默认端口 上述代码中创建了两个键&#xff0c;注意Redis中严格区分大小写&#xff0…

uniapp、微信小程序返回上页面刷新数据

目录 前言&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 方法3&#xff1a; 前言&#xff1a; 返回上页面刷新数据这个功能主要用于在当前页面点击跳转到另一个页面之后&#xff0c;在另一个页面对数据进行了操作&#xff0c;比如&#xff1a;阅读量&#xff0c;然后返…

设计循环队列(c语言)

前言 在上一篇文章中我们了解了关于循环队列的基本特性&#xff1a; 1、当rear front时&#xff0c;表示队列为空 2、当rear 1 front时&#xff0c;表示队列已满 当我们需要实现循环队列时&#xff0c;通常会选择使用链表或数组来存储队列中的元素。而使用数组来实现循环队…