Leetcode---352周赛

周赛题目

2760. 最长奇偶子数组

2761. 和等于目标值的质数对

2762. 不间断子数组

2763. 所有子数组中不平衡数字之和

一、最长奇偶子数组

 这题的数据范围允许用暴力来做,只要我们分别枚举左端点left和右端点right,然后看区间[left,right]是否符合题目条件,然后找到最大值了返回就行,这里就不多做解释了,下面讲解一种更快的算法---滑动窗口

思路:我们先找到符合条件的左端点,再不断向右扩展右端点,并不断更新最长子数组的长度,直到遇到不符合条件的数出现,我们再移动左端点,使得区间再次符合条件,然后继续移动右端点,如此循环,最后返回得到的最长子数组的长度

代码如下

int longestAlternatingSubarray(int* nums, int numsSize, int threshold){int right=0;int ans=0;while(right<numsSize){//找到符合条件的左端点if(nums[right]>threshold||nums[right]%2){right++;continue;}int left=right;right++;while(right<numsSize&&nums[right]<=threshold&&(nums[right-1]%2)!=(nums[right]%2)){ right++;}ans=fmax(ans,right-left);}return ans;
}

二、和等于目标值的质数对

 这题其实也不难,主要是质数的判断比较费时间,如果我们一个个去比较,那么时间很可能会超时,这里需要用埃氏筛或者线性筛,来提前预处理出那些素数

这里简单说明一下埃氏筛的思路:默认所有的数都是素数(即标记为true),从2开始枚举,将2放入素数集合中,再将范围内所有2的倍数标记为false,然后下一个枚举的数是如果是true,就加入素数集合,并将其在范围内的所有倍数标记为false,如果是false,就将其在范围内的所有倍数标记为false,如此循环,就得到了范围内所有的素数

代码如下

int** findPrimePairs(int n, int* returnSize, int** returnColumnSizes){bool prime[n+1];for(int i=0;i<=n;i++)prime[i]=true;for(int i=2;i<n;i++){for(int j=i;j<n/i+1;j++){//这里的写法可以防止越界prime[j*i]=false;}}int**ans=(int**)malloc(sizeof(int*)*100000);*returnSize=0;for(int i=2;i<n;i++){if(!prime[i])continue;if(n-i<i)break;if(prime[n-i]){int*tmp=(int*)malloc(sizeof(int)*2);tmp[0]=i,tmp[1]=n-i;ans[(*returnSize)++]=tmp;}}*returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));for(int i=0;i<*returnSize;i++){(*returnColumnSizes)[i]=2;}return ans;
}

进阶:由于埃氏筛会导致有些数字被重复赋值为false,浪费了时间(如12=2*6=3*4),这里补充讲一下线性筛,也就是防止重复赋值的情况,我们该怎么办?我们只要将枚举到的数字和已经得到的质数相乘,且如果该质数是所枚举数字的因子,直接跳出循环即可,这个算法的证明有兴趣的同学可以自行去百度,这里就不做详细证明了,写一下代码

int** findPrimePairs(int n, int* returnSize, int** returnColumnSizes){bool is_prime[n+1];int primes[n];int k=0;for(int i=0;i<=n;i++)is_prime[i]=true;for(int i=2;i<n;i++){if(is_prime[i])primes[k++]=i;for(int j=0;j<k&&primes[j]*i<n;j++){is_prime[primes[j]*i]=false;if(i%primes[j]==0)break;}}int**ans=(int**)malloc(sizeof(int*)*100000);*returnSize=0;for(int i=2;i<n;i++){if(!is_prime[i])continue;if(n-i<i)break;if(is_prime[n-i]){int*tmp=(int*)malloc(sizeof(int)*2);tmp[0]=i,tmp[1]=n-i;ans[(*returnSize)++]=tmp;}}*returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));for(int i=0;i<*returnSize;i++){(*returnColumnSizes)[i]=2;}return ans;
}

三、不间断子数组

我们先用个例子来找找思路

接下来,我们只需要维护一段区间上的最大值和最小值来保证区间合法就行,那么这题很显然要用到特殊的队列(优先队列)来维护变化区间上的最大值和最小值代码如下

long long continuousSubarrays(int* nums, int numsSize){long long ans=0;int n=numsSize;int q_Max[n],q_Min[n];int h1=0,t1=0,h2=0,t2=0;for(int left=0,right=0;right<numsSize;right++){while(h1<t1&&nums[q_Max[t1-1]]<nums[right]){t1--;}while(h2<t2&&nums[q_Min[t2-1]]>nums[right]){t2--;}q_Max[t1++]=right;q_Min[t2++]=right;while(h1<t1&&h2<t2&&nums[q_Max[h1]]-nums[q_Min[h2]]>2){if(q_Max[h1]<q_Min[h2]){h1++;}else{h2++;}//这里不用担心h1或者h2越界的问题,因为它们就算h1或者h2到达n-1,那么++的必然是另一个//而一旦h1=h2=n-1,就不符合最大值和最小值相差大于2的条件,不用进入循环left=fmin(q_Max[h1],q_Min[h2]);}ans+=right-left+1;}return ans;
}

四、2763. 所有子数组中不平衡数字之和

 

 这题的数据范围允许我们使用暴力做法,即直接枚举左右端点,依次计算每个区间的不平衡数字之和,将它们相加后返回,这里的问题就在于我们如何计算区间内的不平衡数字之和,很多人就会想到题目中要求排序,那我们也排序,但是一旦排序就会改变数组中数字的顺序,所以我们就需要额外空间来存放需要排序的数字,既增加空间复杂度,又增加了时间复杂度,这里其实不用这么复杂,我们继续来举个例子帮助大家打开思路

代码如下

int sumImbalanceNumbers(int* nums, int numsSize){int n=numsSize,ans=0;for(int i=0;i<n;i++){bool visited[n+2];memset(visited,false,sizeof(visited));visited[nums[i]]=true;int cnt=0;for(int j=i+1;j<n;j++){int x=nums[j];if(!visited[x]){cnt+=1-visited[x-1]-visited[x+1];visited[x]=1;}ans+=cnt;}}return ans;
}//介绍另一种写法
int sumImbalanceNumbers(int* nums, int numsSize){int visited[numsSize+2];memset(visited,-1,sizeof(visited));int ans=0;for(int i=0;i<numsSize-1;i++){int cnt=0;visited[nums[i]]=i;for(int j=i+1;j<numsSize;j++){int x=nums[j];if(visited[x]!=i){cnt+=1-(visited[x-1]==i)-(visited[x+1]==i);visited[x]=i;}ans+=cnt;}}return ans;
}

那么有没有O(n)的方法呢?

其实这题还可以用贡献法来求解,即我们来单独讨论每个元素对不平衡数字之和的贡献。

算法的思想:假设我们要计算x这个数对数组不平衡数字的贡献,那么我们向左边寻找离x最近的x-1或x,在向右边寻找离x最近的x-1(之所以不找x+1,是因为当我们计算x+1这个数的贡献时,就会向左找x,所以没必要找,而右边不找x的理由同上)这样我们就能知道x存在的子数组的个数(用乘法原理),由此来推断x对不平衡数字的贡献,但是这有一个问题:当x是所在子数组的最小值时,它的贡献就是0,我们需要减去这部分多算的贡献,而每一个元素x充当最小值的子数组的数量就是原数组的子数组的数量,也就是n(n+1)/2---注意子数组要求连续

代码如下

int sumImbalanceNumbers(int* nums, int numsSize){int n=numsSize,ans=0;int left[n];int idx[n+1];memset(idx,-1,sizeof(idx));for(int i=0;i<n;i++){int x=nums[i];left[i]=fmax(idx[x-1],idx[x]);idx[x]=i;}for(int i=0;i<n+1;i++){idx[i]=n;}for(int i=n-1;i>=0;i--){int right=idx[nums[i]-1];ans+=(i-left[i])*(right-i);idx[nums[i]]=i;}return ans-n*(n+1)/2;
}

最后不要忘记点赞,评论加收藏哦!!!

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

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

相关文章

flutter3.7版本下使用flutter boost解决使用platview崩溃或异常问题

背景 工程使用了混合开发&#xff0c;使用flutter boost插件&#xff0c;flutter 的activity1 frament1 跳转activity2 frament2&#xff0c;frament1 包含platformView&#xff0c;按照上面老哥解决崩溃问题的基础上&#xff0c;出现activity2 frament2返回activity1 framen…

golang 协程的实现原理

核心概念 要理解协程的实现, 首先需要了解go中的三个非常重要的概念, 它们分别是G, M和P, 没有看过golang源代码的可能会对它们感到陌生, 这三项是协程最主要的组成部分, 它们在golang的源代码中无处不在. G (goroutine) G是goroutine的头文字, goroutine可以解释为受管理的…

C++图形开发(6):落下后能弹起的小球

文章目录 1.重复下落的小球2.落下后能弹起的小球3.能上下反弹的小球4.符合重力的能上下反弹的小球 今天我们来尝试实现一个落地后可以弹起的小球 1.重复下落的小球 首先&#xff0c;我们要来实现一个小球的重复下落 我们知道&#xff0c;在前面的代码中&#xff08;详见C图形…

ChatGPT与Excel结合_编写VBA宏

先来解释下什么是Excel vba宏 ⭐Excel VBA宏&#xff08;Visual Basic for Applications&#xff09;是一种用于在Microsoft Excel中自动化和扩展功能的编程语言。VBA允许用户编写自定义的脚本或宏&#xff0c;以便通过执行一系列指令来自动完成特定任务。 使用Excel VBA宏&a…

基于改进莱维飞行和混沌映射的金鹰优化算法(10种混沌映射随意切换),附matlab代码

“ 本篇文章对金鹰优化算法进行改进&#xff0c;首先通过引入混沌映射机制&#xff0c;对其群体进行初始化&#xff0c;增加金鹰个体的多样性&#xff1b;然后在金鹰个体的位置更新公式上引入改进的莱维飞行机制&#xff0c;提高搜索精度&#xff0c;帮助金鹰个体跳出局部最优。…

Work20230705

//main.c #include "uart4.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); }int main() {while(1){//将获取到的字符1发送到终端//hal_put_char(hal_get_char()1);hal_put_string…

监控系统Zabbix

zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监控软件&#xff0c;我们可以&#xff1a; 通过一个友好的界面进行浏览整个网站…

【设计模式】第十七章:状态模式详解及应用案例

系列文章 【设计模式】七大设计原则 【设计模式】第一章&#xff1a;单例模式 【设计模式】第二章&#xff1a;工厂模式 【设计模式】第三章&#xff1a;建造者模式 【设计模式】第四章&#xff1a;原型模式 【设计模式】第五章&#xff1a;适配器模式 【设计模式】第六章&…

谷歌Bard入门指南

文章目录 谷歌Bard入门指南一、简介二、使用指南三、中文化3.1 中文提问3.2 中文回答 四、Hello Game五、亮点 谷歌Bard入门指南 一、简介 Bard 是一个大型语言模型&#xff0c;也称为对话式 AI 或聊天机器人&#xff0c;经过训练&#xff0c;内容丰富且全面。Bard 接受过大量…

Tkinter_使用Progressbar创建和管理进度条

前言 Progressbar是Tkinter库中的一个小部件&#xff0c;用于创建和管理进度条。它可以在图形用户界面中显示任务的进度&#xff0c;并提供了多种样式和配置选项。 使用Progressbar&#xff0c;你可以按照固定或不确定的进度展示任务的进行状态。它可以显示任务完成的百分比&am…

matplotlib设置坐标轴为象限模式

import numpy as np import matplotlib.pyplot as pltx np.linspace(-np.pi, np.pi, 1000) cosy np.cos(x) siny np.sin(x)plt.xlim(min(x), max(x)) plt.ylim(min(cosy), max(cosy)0.5) plt.plot(x, cosy) plt.plot(x, siny) # 设置坐标刻度 plt.xticks([-np.pi, -np.pi/2,…

微前端(拆分和细化,整合历史系统)

接入微前端 项目背景说明 假如我们完成了基于Vue2的项目&#xff0c;假设另外一个团队的小伙伴来实现前台可视化部分&#xff0c;他们使用的是最新的Vue3技术栈&#xff0c;现在有一个需求&#xff0c;他们的前台项目想直接使用我们的登录功能&#xff0c;获得token&#xff…