算法刷题day22:双指针
目录
- 引言
- 概念
- 一、牛的学术圈I
- 二、最长连续不重复序列
- 三、数组元素的目标和
- 四、判断子序列
- 五、日志统计
- 六、统计子矩阵
引言
关于这个双指针算法,主要是用来处理枚举子区间的事,时间复杂度从 O ( N 2 ) O(N^2) O(N2) 降为 O ( N ) O(N) O(N) ,所以还是很方便的,而且枚举这类题出的还是很常见的,所以这个算法还是尤为重要的。加油!
概念
双指针算法:首先要满足单调性,二分是元素的单调性、二段性,这个指的是区间的单调性。
双指针模板:
for(int i = 0, j = 0; i < n; ++i)
{while(j < n && check(i,j)) j++;//该题逻辑
}
一、牛的学术圈I
标签:二分
思路:像这种求最大/最小的问题,基本上都可以用二分。我们不讨论最大值,我们讨论该h指数是否能达到,然后用二分来逼近能成立的最大值,显然该题是具有二段性的,具体长如下这样。然后就是 c h e c k check check 函数了,因为先统计大于等于 m i d mid mid 的个数,再统计满足 a [ i ] + 1 = m i d a[i] + 1 = mid a[i]+1=mid 的个数,与 l l l 取最小值,最后比较是否 r e s ≥ m i d res \geq mid res≥mid 。

题目描述:
由于对计算机科学的热爱,以及有朝一日成为 「Bessie 博士」的诱惑,奶牛 Bessie 开始攻读计算机科学博士学位。经过一段时间的学术研究,她已经发表了 N 篇论文,并且她的第 i 篇论文得到了来自其他研究文献的 ci 次引用。Bessie 听说学术成就可以用 h 指数来衡量。h 指数等于使得研究员有至少 h 篇引用次数不少于 h 的论文的最大整数 h。例如,如果一名研究员有 4 篇论文,引用次数分别为 (1,100,2,3),则 h 指数为 2,然而若引用次数为 (1,100,3,3)则 h 指数将会是 3。为了提升她的 h 指数,Bessie 计划写一篇综述,并引用一些她曾经写过的论文。由于页数限制,她至多可以在这篇综述中引用 L 篇论文,并且她只能引用每篇她的论文至多一次。请帮助 Bessie 求出在写完这篇综述后她可以达到的最大 h 指数。注意 Bessie 的导师可能会告知她纯粹为了提升 h 指数而写综述存在违反学术道德的嫌疑;我们不建议其他学者模仿 Bessie 的行为。输入格式
输入的第一行包含 N 和 L。
第二行包含 N 个空格分隔的整数 c1,…,cN。输出格式
输出写完综述后 Bessie 可以达到的最大 h 指数。数据范围
1≤N≤105,0≤ci≤105,0≤L≤105
输入样例1:
4 0
1 100 2 3
输出样例1:
2
样例1解释
Bessie 不能引用任何她曾经写过的论文。上文中提到,(1,100,2,3) 的 h 指数为 2。输入样例2:
4 1
1 100 2 3
输出样例2:
3
如果 Bessie 引用她的第三篇论文,引用数会变为 (1,100,3,3)。上文中提到,这一引用数的 h 指数为 3。
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e5+10;int n, m;
int a[N];bool check(int mid) // 检查能否到mid
{int res = 0, t = 0;for(int i = 0; i < n; ++i){if(a[i] >= mid) res++;if(a[i] + 1 == mid) t++;}t = min(m, t);res += t;return res >= mid;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m;for(int i = 0; i < n; ++i) cin >> a[i];int l = 0, r = 1e5;while(l < r){int mid = (LL)l + r + 1 >> 1;if(check(mid)) l = mid;else r = mid - 1;}cout << r << endl;return 0;
}
二、最长连续不重复序列
标签:双指针
思路:模板题。核心就是 [ j , i ] [j,i] [j,i] 维护的是一段有效的序列, i i i 是一值往前走的,用 c n t cnt cnt 来记录每一个值出现的次数,如果重复了,那肯定是 i i i 和 j j j 所对应的元素重复了, j j j 往前走即可,然后找最大值。
题目描述:
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼105 范围内),表示整数序列。输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。数据范围
1≤n≤105
输入样例:
5
1 2 2 3 5
输出样例:
3
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e5+10;int n;
int a[N], cnt[N];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;for(int i = 0; i < n; ++i) cin >> a[i];int res = 0;for(int i = 0, j = 0; i < n; ++i){cnt[a[i]]++;while(j < i && cnt[a[i]] > 1) cnt[a[j++]]--;res = max(res, i - j + 1);}cout << res << endl;return 0;
}
三、数组元素的目标和
标签:哈希、双指针
思路1:就是找两个数组中和为 k e y key key 的两个下标,直接先把第一个数组按元素值存入哈希表,然后遍历第二个数组如果存在就输出即可。
思路2:由于都是升序的, i i i 从最小值遍历, j j j 从最大值遍历,如果值总和变小了, i i i 右移,如果变大了, j j j 左移,直到相等。
题目描述:
给定两个升序排序的有序数组 A 和 B,以及一个目标值 x。数组下标从 0 开始。请你求出满足 A[i]+B[j]=x 的数对 (i,j)。数据保证有唯一解。输入格式
第一行包含三个整数 n,m,x,分别表示 A 的长度,B 的长度以及目标值 x。第二行包含 n 个整数,表示数组 A。第三行包含 m 个整数,表示数组 B。输出格式
共一行,包含两个整数 i 和 j。数据范围
数组长度不超过 105。同一数组内元素各不相同。1≤数组元素≤109
输入样例:
4 5 6
1 2 4 7
3 4 6 8 9
输出样例:
1 1
示例代码1: 哈希表
#include <bits/stdc++.h>using namespace std;typedef long long LL;int n, m, k;
unordered_map<int,int> mmap;int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m >> k;for(int i = 0; i < n; ++i){int t; cin >> t;mmap[t] = i;}for(int i = 0; i < m; ++i){int t; cin >> t;if(mmap.count(k-t)) {cout << mmap[k-t] << " " << i << endl;break;}}return 0;
}
示例代码2: 双指针
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e5+10;int n, m;
LL k;
int a[N], b[N];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m >> k;for(int i = 0; i < n; ++i) cin >> a[i];for(int i = 0; i < m; ++i) cin >> b[i];int i = 0, j = m - 1;for(; i < n && j > -1; ++i){while(j > -1 && a[i] + b[j] > k) j--;if(j > -1 && (LL)a[i] + b[j] == k) break;}cout << i << " " << j << endl;return 0;
}
四、判断子序列
标签:双指针、模板题
思路:双指针模板,没啥说的。
题目描述:
给定一个长度为 n 的整数序列 a1,a2,…,an 以及一个长度为 m 的整数序列 b1,b2,…,bm。请你判断 a 序列是否为 b 序列的子序列。子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5} 是序列 {a1,a2,a3,a4,a5} 的一个子序列。输入格式
第一行包含两个整数 n,m。
第二行包含 n 个整数,表示 a1,a2,…,an。
第三行包含 m 个整数,表示 b1,b2,…,bm。输出格式
如果 a 序列是 b 序列的子序列,输出一行 Yes。
否则,输出 No。数据范围
1≤n≤m≤105,109≤ai,bi≤109
输入样例:
3 5
1 3 5
1 2 3 4 5
输出样例:
Yes
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e5+10;int n, m;
int a[N], b[N];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m;for(int i = 0; i < n; ++i) cin >> a[i];for(int j = 0; j < m; ++j) cin >> b[j];int i = 0, j = 0;while(i < n && j < m){if(a[i] == b[j]) i++;j++;}if(i == n) puts("Yes");else puts("No");return 0;
}
五、日志统计
标签:枚举、双指针
思路:一般这种题都是遍历订单,而我看这道题要按 i d id id 号由小到大输出,那我就遍历 i d id id 号了,然后找出满足条件的输出就行了,我用 v e c t o r + 数组 vector+数组 vector+数组 来存,第 i i i 号 v e c t o r vector vector 代表 i d id id 号为 i i i 的订单时间, v e c t o r vector vector 里存的是该 i d id id 的点赞时间,首先如果数量够 k k k 个,然后由小到大排序,遍历每 k k k 个时间,判断是否间隔时间在 d d d 以内,如果是输出即可。
题目描述:
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。其中每一行的格式是:ts id 表示在 ts 时刻编号 id 的帖子收到一个”赞”。现在小明想统计有哪些帖子曾经是”热帖”。如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。输入格式
第一行包含三个整数 N,D,K。以下 N 行每行一条日志,包含两个整数 ts 和 id。输出格式
按从小到大的顺序输出热帖 id。每个 id 占一行。数据范围
1≤K≤N≤105,0≤ts,id≤105,1≤D≤10000
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e5+10;int n, d, k;
vector<int> logs[N]; // 统计第i号订单的日期int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> d >> k;for(int i = 0; i < n; ++i){int ts, id;cin >> ts >> id;logs[id].push_back(ts);}for(int i = 0; i < N; ++i) // 遍历每一个id{if(logs[i].size() >= k){sort(logs[i].begin(), logs[i].end()); // 给其时间排序for(int j = 0; j + k - 1 < logs[i].size(); ++j){if(logs[i][j+k-1] - logs[i][j] + 1 <= d) {cout << i << endl;break;}}}}return 0;
}
六、统计子矩阵
标签:前缀和、二分
思路:本来用前缀和直接做的话,时间复杂度在 O ( N 4 ) O(N^4) O(N4) ,明显超时了。由题意得元素没有负数,所以满足单调性,可以用上下界限拿前缀和处理,左右拿双指针处理,这样时间复杂度就降为了 O ( N 3 ) O(N^3) O(N3) 刚好能过。
题目描述:
给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小 1×1,最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K?输入格式
第一行包含三个整数 N,M 和 K。之后 N 行每行包含 M 个整数,代表矩阵 A。输出格式
一个整数代表答案。数据范围对于 30% 的数据,N,M≤20,
对于 70% 的数据,N,M≤100,
对于 100% 的数据,1≤N,M≤500;0≤Aij≤1000;1≤K≤2.5×108。输入样例:
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
输出样例:
19
样例解释
满足条件的子矩阵一共有 19,包含:大小为 1×1 的有 10 个。大小为 1×2 的有 3 个。大小为 1×3 的有 2 个。大小为 1×4 的有 1 个。大小为 2×1 的有 3 个。
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 510;int n, m, k;
int s[N][N];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m >> k;for(int i = 1; i <= n; ++i){for(int j = 1; j <= m; ++j){cin >> s[i][j];s[i][j] += s[i-1][j];}}LL res = 0;for(int i = 1; i <= n; ++i){for(int j = i; j <= n; ++j){for(int l = 1, r = 1, sum = 0; r <= m; ++r){sum += s[j][r] - s[i-1][r];while(l <= m && sum > k) sum -= s[j][l] - s[i-1][l], l++;res += r - l + 1;}}}cout << res << endl;return 0;
}
相关文章:
算法刷题day22:双指针
目录 引言概念一、牛的学术圈I二、最长连续不重复序列三、数组元素的目标和四、判断子序列五、日志统计六、统计子矩阵 引言 关于这个双指针算法,主要是用来处理枚举子区间的事,时间复杂度从 O ( N 2 ) O(N^2) O(N2) 降为 O ( N ) O(N) O(N) …...
山人求道篇:八、模型的偏差与交易认知
原文引用https://mp.weixin.qq.com/s/xvxatVseHK62U7aUXS1B4g “ CTA策略一波亏完全年,除了交易执行错误导致的以外,这类策略都是多因子策略,一般会用机器学习组合多因子得出一个信号来进行交易。规则型策略几乎不会出现一波做反亏完全年的情况。这是有以下几个原因的: 多…...
MySQL 元数据锁及问题排查(Metadata Locks MDL)
"元数据"是用来描述数据对象定义的,而元数据锁(Metadata Lock MDL)即是加在这些定义上。通常我们认为非锁定一致性读(简单select)是不加锁的,这个是基于表内数据层面,其依然会对表的元…...
JS中的函数
1、函数形参的默认值 JavaScript函数有一个特别的地方,无论在函数定义中声明了多少形参,都可以传入任意数量的参数,也可以在定义函数时添加针对参数数量的处理逻辑,当已定义的形参无对应的传入参数时,为其指定一个默认…...
微信小程序开发常用的布局
在微信小程序开发中,常用的布局主要包括以下几种: Flex 布局:Flex 布局是一种弹性盒子布局,通过设置容器的属性来实现灵活的布局方式。它可以在水平或垂直方向上对子元素进行对齐、排列和分布。Flex 布局非常适用于创建响应式布局…...
Effective C++ 学习笔记 条款10 令operator=返回一个reference to *this
关于赋值,有趣的是你可以把它们写成连锁形式: int x, y, z; x y z 15; // 赋值连锁形式同样有趣的是,赋值采用右结合律,所以上述连锁赋值被解析为: x (y (z 15));这里15先被赋值给z,然后其结果&…...
算法简单试题
一、选择题 01.一个算法应该是( B ). A.程序 B.问题求解步骤的描述 C.要满足五个基本特性 D.A和C 02.某算法的时间复杂度为O(n),则表示该…...
CSS 自测题 -- 用 flex 布局绘制骰子(一、二、三【含斜三点】、四、五、六点)
一点 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>css flex布局-画骰子</title><sty…...
蓝桥集训之牛的学术圈 I
蓝桥集训之牛的学术圈 I 核心思想:二分 确定指数x后 判断当前c[i]是否>x(满足条件) 并记录次数同时记录 1后满足条件的个数最后取bns和m的最小值 为满足条件的元素个数ansbns为当前指数x下 满足条件的元素个数 #include <iostream>#include <cstring…...
软件设计师软考题目解析21 --每日五题
想说的话:要准备软考了。0.0,其实我是不想考的,但是吧,由于本人已经学完所有知识了,只是被学校的课程给锁在那里了,不然早找工作去了。寻思着反正也无聊,就考个证玩玩。 本人github地址…...
python读写json文件详解
在Python中,可以使用json模块来读写JSON格式的文件。下面是一个详细的示例,演示了如何读写JSON文件: import json# 写入JSON文件 data {"name": "John","age": 30,"city": "New York" }…...
#include<ros/ros.h>头文件报错
快捷键 ctrl shift B 调用编译,选择:catkin_make:build)(要先在vscode上添加扩展:ros) 可以点击配置设置为默认,修改.vscode/tasks.json 文件 修改.vscode/tasks.json 文件,否则ros.h头文件会报错 内容修改为以下内…...
mybatis单表curd笔记(尚硅谷
Mybatis 11111ibatis和mybatis不同 查询文档mybatis的日志输出id赋值输入(向sql语句传入数据单个简单类型单个实体对象多个简单类型map类型 输出数据的指定单个简单类型单个实体类型输出map类型输出list输出类型主键回显(自增长类型主键回显(…...
在线重定义-操作步骤
第一步:验证表是否能被在线重定义 验证是否能按主键重定义(默认,最后一次参数可以不加) 1 2 3 4 begin --dbms_redefinition.can_redef_table(scott,tb_cablecheck_equipment_bak); dbms_redefinition.can_redef_table(scot…...
16:00面试,16:06就出来了,问的问题过于变态了。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到2月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…...
基于dashscope在线调用千问大模型
前言 dashscope是阿里云大模型服务平台——灵积提供的在线API组件。基于它,无需本地加载大模型,通过在线方式访问云端大模型来完成对话。 申请API key 老规矩:要想访问各家云端大模型,需要先申请API key。 对于阿里云&#x…...
【Python】可变数据类型 不可变数据类型 || hash
🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…...
MySQL 篇-深入了解多表设计、多表查询
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 多表设计概述 1.1 多表设计 - 一对多 1.2 多表设计 - 一对一 1.3 多表设计 - 多对多 2.0 多表查询概述 2.1 多表查询 - 内连接 2.2 多表查询 - 外连接 2.3 多表查…...
【Java】Spring的ReflectionUtils类常用方法学习笔记
目录 ReflectionUtils介绍 常用方法 访问字段 方法调用 处理回调 示例 脑容量不够了,以简单的小知识作为一天的结尾吧(悲 ReflectionUtils介绍 ReflectionUtils是Spring Framework中非常实用的一个工具类,为开发人员提供了简便的反射操作方法&am…...
内存函数详解
1. memcpy函数 void * memcpy ( void * destination, const void * source, size_t num ); 1.1 函数的功能,使用与注意事项 1. memcpy函数的作用是内存拷贝,即将source指向的空间中的num个字节拷贝到destination指向的空间中去,然后返回de…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
