LeetCode---386周赛

题目列表

3046. 分割数组

3047. 求交集区域内的最大正方形面积

3048. 标记所有下标的最早秒数 I

3049. 标记所有下标的最早秒数 II

一、分割数组

这题简单的思维题,要想将数组分为两个数组,且分出的两个数组中数字不会重复,很显然一个数字出现次数最多两次,代码如下

class Solution {
public:bool isPossibleToSplit(vector<int>& nums) {unordered_map<int,int>mp;for(auto x:nums)if(++mp[x]>2)return false;return true;}
};

二、求交集区域内的最大正方形面积

直接暴力枚举出所有两个矩阵的交集的正方形面积,求解出最大值,代码如下

class Solution {
public:long long largestSquareArea(vector<vector<int>>& bLeft, vector<vector<int>>& tRight) {int n=bLeft.size(),w=0;for(int i=1;i<n;i++){for(int j=i-1;j>=0;j--){//挑选四个直线,围成交集区域int x_l=max(bLeft[i][0],bLeft[j][0]);int x_r=min(tRight[i][0],tRight[j][0]);int y_top=min(tRight[i][1],tRight[j][1]);int y_bottom=max(bLeft[i][1],bLeft[j][1]);if(x_l<x_r&&y_top>y_bottom){//确保会有交集w=max(w,min(x_r-x_l,y_top-y_bottom));}}    }return 1LL*w*w;}
};

三、标记所有下标的最早秒数I

题目问最早秒数,我们正常来说都会想到贪心 / 从小到大枚举验证,其中贪心,大家可以去试着想想,因为需要从左往右遍历时间,而我们不知道后面changeIndices[]的情况,所以就不能去决定这一步去做什么操作会比较好,也就很难去贪心。

那么我们来看看枚举验证行不行?一旦数据不好,估计得验证O(n)次,大概率会超时,所以我们要降低时间复杂度,怎么做?--- 二分

1、是否满足二分条件,即单调性?

根据题目所给的条件,我们知道时间越多,我们越有可能将nums[i]减为零,越有可能标记所有下标,即秒数越多越能满足条件,符合单调性,可以二分

2、如何验证是否能在k秒内标记所有下标,即bool check(int k)函数如何写?(如果下面的内容不理解,可以先看看下面加粗的内容)

首先,由于changeIndices[]是不可预知的,即标记操作是不可控的,所以我们优先考虑什么时候标记下标的问题,根据贪心,我们肯定是越晚标记下标越好,这样会有更多的时间将nums[i]减为零,所以我们要知道每个下标的最晚标记时间

然后在来考虑是否能在下标 i 的最晚标记时间之前,将nums[i]减为零,这个就很简单了,我们只要维护一个cnt来记录到目前为止有多少时间,然后在到达某个最晚标记时间时,如果cnt>=nums[i],cnt = cnt - nums[i],否则直接返回false,如果所有下标都能被标记就返回true (很显然check函数的时间复杂度为O(n),所以暴力枚举会超时,需要二分)

如果大家不是很理解,可以将这题转换成考试来看,即一共有n门课程,nums[i]表示第 i 门课程的复习天数,changeIndices[i]表示第 i 天进行考试的课程,问复习完并考完所有课程的最少天数是多少?相信经历了这么多年考试的你们,会更容易理解复习和考试的关系(doge)

代码如下

/*
将问题转换成一共有n门课程,第i门课程的复习时间为nums[i]天
changeIndices[i]课程的考试时间为第i天
复习并考完所有课程的最小时间由于考试时间是固定的,我们需要优先考虑考试时间
=> 考试时间越靠后,就会有更加充分的时间用来复习
=> 具有单调性
=> 可以二分check函数如何去判断是否能复习考完所有的考试?
1、贪心,我们把每门课程的考试时间尽可能往后拖延  last[]记录每门课程的最迟考试时间
2、如果考试数目<=课程数,return false; // 可以优化的点否则我们从前往后遍历天数,优先复习考试时间近的科目,看能否在考试之前完成复习
*/class Solution {
public:int earliestSecondToMarkIndices(vector<int>& nums, vector<int>& changeIndices) {int n=nums.size(),m=changeIndices.size();auto check=[&](int k)->bool{vector<int>last(n,-1); // 记录下标i的最晚标记时间,即最晚考试时间for(int i=0;i<k;i++)last[changeIndices[i]-1]=i;for(auto x:last)if(x<0) // 表示有的下标没有被标记的时间,即有的课程没有考试return false;int cnt = 0;for(int i=0;i<k;i++){int idx = changeIndices[i] - 1;if(last[idx]==i){//表示下标idx到了最后的被标记的时间,即课程到了考试的最后截止时间cnt-=nums[idx];if(cnt<0) return false;//没有足够的时间将nums[idx]置为0,即没有足够的时间复习课程}else{cnt++;}}return true;};int l=1,r=m;while(l<=r){int mid = l+(r-l)/2;if(check(mid)) r=mid-1;else l=mid+1;}return l>m?-1:l;}
};

四、标记所有下标的最早秒数II

有情提醒一下: 该题和第三题的题目并不一样。

在这题中,操作变得更加复杂了,但其实我们还是可以借鉴第三题的思路:

首先,这题依旧能够二分,因为时间越多,越有可能标记所有下标,但是check函数的思路不一样了,我们要优先考虑清零操作,因为它是不可控的(为了方便描述,这里将题目中的几个操作分别称为减一、清零、标记)。

【如果下面的内容看不太明白,依旧可以带入上一题说的考试模型,帮助你理解---减一操作:花费一天复习一门课,清空操作:花费一天速通一门课,标记:选择一天用来考试】

1)这里就要讨论一下:清零操作和减一操作什么时候用比较合适?

1、如果nums[i]用过减一操作,还需要用清零操作吗?没必要,因为如果能清零,就没必要在花多余的时间进行减一,可以将多出的时间给其他的nums[j]

2、如果nums[i]用过清零操作,也就不需要在进行减一操作了

结论:对于nums[i]要么执行清零操作,要么就执行减一操作,不能混用

2)根据贪心:我们肯定是能清零就尽量的去执行清零,让被清零的nums[i]有更多的时间被减为0

1、清零操作是越早越好还是越晚越好?肯定是越早越好,因为我们还需要有多余的时间去标记,所以我们需要从后往前遍历,去看是否有多余的时间去标记下标,所以我们要记录每个下标的最早清零时间

2、什么时候不需要用清零操作?

  • nums[i]==0时,不需要
  • nums[i]==1时,也不需要,因为减一操作也能做到清零,且可以在任意时间执行

除了上面的两种情况,还有一种特殊的情况,即用完清零操作之后就没时间进行标记了,这里我们不是只能进行对 i 下标进行nums[i]次减一操作,而是可以看之前进行清空操作的下标中nums[j]的最小值 是否 比nums[i]小,如果小,那么显然我们可以对 j 下标进行nums[j]次减一操作,同时nums[i]就会有时间进行清零和标记,这样的方案显然会更优----反悔贪心

我们从后往前遍历,同时维护用来标记/减一的时间cnt 和 需要减一和标记的总时间sum(都不包含进行清零操作的下标的标记时间)具体如何维护看下面的代码。

class Solution {
public:int earliestSecondToMarkIndices(vector<int>& nums, vector<int>& changeIndices) {int n=nums.size(),m=changeIndices.size();long long total = n;for(auto x:nums) total += x;            vector<int>first_d(n,-1);for(int i=m-1;i>=0;i--)first_d[changeIndices[i]-1]=i;auto check=[&](int k)->bool{priority_queue<int,vector<int>,greater<int>> q;int cnt = 0;// 减一复习并考试的课程的所有时间long long slow = total;//记录减一操作的nums[i]及其标记需要的时间,一开始默认全用减一操作for(int i=k-1;i>=0;i--){int idx=changeIndices[i]-1;if(nums[idx]<=1||i!=first_d[idx]){cnt++;continue;}if(cnt==0){if(q.empty()||nums[idx]<=q.top()){//只能进行减一操作cnt++;continue;}slow += q.top()+1;q.pop();cnt += 2;}slow -= nums[idx]+1;cnt--;q.push(nums[idx]);}return cnt>=slow;};int l=1,r=m;while(l<=r){int mid=l+(r-l)/2;if(check(mid)) r=mid-1;else l=mid+1;}return l>m?-1:l;}
};

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

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

相关文章

2024第二次培训:win11系统下使用nginx、JDK、mysql搭建基于vue2、java前后端分离的web应用运行环境

一.背景 公司安排了带徒弟的任务&#xff0c;给培训写点材料。前面分开介绍了mysql、jdk、nginx的安装&#xff0c;都只是零星的介绍&#xff0c;只能算零散的学习。学习了有什么用呢&#xff1f;能解决什么问题&#xff1f;能完成什么工作&#xff1f; 今天我们要用之前的几篇…

高中数学:分式函数值域的求法

一、求值域的两种基本思路 1、根据函数图像和定义域求出值域。 难点&#xff1a;画出函数图像 2、研究函数单调性和定义域求出值域。 本篇主要讲一下&#xff0c;画图法求值域 二、函数图像画法 高中所学的分式函数&#xff0c;基本由反比例函数平移得到。 复杂分式函数图…

web漏洞与规避

文章目录 一、XSS 跨站脚本攻击1.1 XSS攻击的主要类型反射型XSS存储型XSSDOM型XSS 1.2 前端开发如何应对XSS 二、CSRF 跨站请求伪造2.1 CSRF例子2.2 前端开发如何应对CSRF 三、SQL 注入3.1 前端如何防御SQL注入 四、前端如何使用CSP 一、XSS 跨站脚本攻击 攻击者通过在受害者的…

Day12:信息打点-Web应用源码泄漏开源闭源指纹识别GITSVNDS备份

目录 开源-CMS指纹识别源码获取方式 闭源-习惯&配置&特性等获取方式 闭源-托管资产平台资源搜索监控 思维导图 章节点 Web&#xff1a;语言/CMS/中间件/数据库/系统/WAF等 系统&#xff1a;操作系统/端口服务/网络环境/防火墙等 应用&#xff1a;APP对象/API接口/微…

【Python】进阶学习:pandas--如何根据指定条件筛选数据

【Python】进阶学习&#xff1a;pandas–如何根据指定条件筛选数据 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望…

synchrosized 的可重入特性、死锁、哲学家就餐问题以及解决死锁的方法等干货

文章目录 &#x1f490;synchrosized的可重入特性关于死锁&#xff1a;哲学家就餐问题&#x1f4a1;如何避免/解决死锁 &#x1f490;synchrosized的可重入特性 可重入特性&#xff1a;当一个线程针对一个对象同时加锁多次&#xff0c;不会构成死锁&#xff0c;这样的特性称为…

NoSQL--虚拟机网络配置

目录 1.初识NoSQL 1.1 NoSQL之虚拟机网络配置 1.1.1 首先&#xff0c;导入预先配置好的NoSQL版本到VMware Workstation中 1.1.2 开启虚拟机操作&#xff1a; 1.1.2.1 点击开启虚拟机&#xff1a; 1.1.2.2 默认选择回车CentOS Linux&#xff08;3.10.0-1127.e17.x86_64) 7 …

今日Arxiv最热NLP大模型论文:Llama-2上下文扩大48倍的方法来了,港大发布,无需训练

引言&#xff1a;大语言模型的长上下文理解能力 在当今的人工智能领域&#xff0c;大语言模型&#xff08;Large Language Models&#xff0c;简称LLMs&#xff09;的长上下文理解能力成为了一个重要的研究方向。这种能力对于模型来说至关重要&#xff0c;因为它使得LLMs能够有…

精品SSM的教学管理系统课程作业成绩

《[含文档PPT源码等]精品基于SSM的教学管理系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xff1a;HTML5,CSS3、Jav…

<网络安全>《63 微课堂<第3课 旁路部署和串行部署是什么?>》

1、串联和并联概念 串联和并联是物理学上的概念。 串联电路把元件逐个顺次连接起来组成的电路。如图&#xff0c;特点是&#xff1a;流过一个元件的电流同时也流过另一个。 并联电路把元件并列地连接起来组成的电路&#xff0c;如图&#xff0c;特点是&#xff1a;干路的电流…

Ps:快照

“历史记录” History面板可分为快照区和历史记录状态区两个部分。 Photoshop 的快照 snapshot功能允许用户保存当前工作状态的完整副本&#xff0c;这包括图像的所有图层&#xff08;包括图层可见性&#xff09;、图层样式、选区以及颜色模式、位深度等其他属性。 通过创建当前…

一份在互联网公司干了八年的经验分享

一份在互联网公司干了八年的经验分享 一晃在这一行已经摸爬滚打8年有余&#xff0c;虽科班毕业&#xff0c;也不是什么名校&#xff0c;学校的计算机氛围没那么浓厚&#xff0c;我基本上是在工作之后才开始正儿八经的学习编程&#xff0c;一边啃书本敲代码&#xff0c;一边是上…