基础算法
本人对于基础算法的刷题
奋斗吧!骚年!
一名爱健身的软件工程本科生
展开
-
基础算法:判断子序列—双指针
题目: AcWing 2816. 判断子序列给定一个长度为 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 序列原创 2022-04-27 20:05:07 · 163 阅读 · 0 评论 -
基础算法:数组元素的目标和—双指针
题目: AcWing 800. 数组元素的目标和给定两个升序排序的有序数组 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≤数组元素≤1原创 2022-04-27 19:50:48 · 273 阅读 · 0 评论 -
基础算法:最长连续不重复子序列—双指针
双指针算法C++模板:for (int i = 0, j = 0; i < n; i ++ ){ while (j < i && check(i, j)) j ++ ; // 具体问题的逻辑}常见问题分类: (1) 对于一个序列,用两个指针维护一段区间 (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作双指针算法理解:当一个序列的时候,如果我们使用朴素的方法直接遍历我们固定起点为0,遍历终点,固定起点为1,遍原创 2022-04-27 19:27:53 · 128 阅读 · 0 评论 -
基础算法:区间合并
区间合并C++模板:// 将所有存在交集的区间合并void merge(vector<PII> &segs){ vector<PII> res; sort(segs.begin(), segs.end()); int st = -2e9, ed = -2e9; for (auto seg : segs) if (ed < seg.first) { if (st != -2e原创 2022-04-27 15:31:44 · 166 阅读 · 0 评论 -
基础算法:区间和—离散化
离散化C++模板:vector<int> alls; // 存储所有待离散化的值sort(alls.begin(), alls.end()); // 将所有值排序alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素// 二分求出x对应的离散化的值int find(int x) // 找到第一个大于等于x的位置{ int l = 0, r = alls.size() - 1; whi原创 2022-04-26 23:59:04 · 253 阅读 · 0 评论 -
基础算法:二进制中1的个数—位运算
位运算C++模板:求n的第k位数字: n >> k & 1返回n的最后一位1:lowbit(n) = n & -n位运算理解:n>>k:代表n右移k位 比如 000011>>1 = 000001 前面会补零(所以第几位是从0开始计算)n&1:表示最后一位是否为1比如:n=3=0011 而1是0001 则3&1= 0011&0001 为0001可以用来判断最后一位是否为1lowbit(x):返回最后一位1 (x&原创 2022-04-26 00:02:29 · 1886 阅读 · 0 评论 -
基础算法:二维差分
二维差分C++模板:给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:S[x1, y1] += cS[x2 + 1, y1] -= cS[x1, y2 + 1] -= cS[x2 + 1, y2 + 1] += c二维差分理解:如果我们只对(x1, y1) (x2, y2) 区域+c,则S[x1, y1] + c 表示整个蓝色区域+cS[x2 + 1, y1] - c表示紫色区域-cS[x1, y2 + 1] - c表示绿色区域-cS[x2 + 1,原创 2022-04-25 21:12:46 · 555 阅读 · 0 评论 -
基础算法:一维差分
一维差分C++模板://a表示原数组,b表示差分数组b[i]=a[i]-a[i-1] //差分就是第i个值和前一个值的差值给区间[l, r]中的每个数加上c:b[l] += c, b[r + 1] -= c一维差分理解:1.差分就是前缀和的逆运算(a[i]=b[1]+b[2]+…b[i])2.差分的作用就是快速实现将数组部分加上一个数例如:如果对b[l]加c则表示l后面的值都会加上c(因为计算原数组都会加上c)如果对b[r+1]减c则r+1后面的值都会减c那么前两步合起来,则可以表示原创 2022-04-25 20:20:02 · 495 阅读 · 0 评论 -
基础算法:二维前缀和
二维前缀和C++模板:S[i, j] = 第i行j列格子左上部分所有元素的和S[i, j] = S[i-1,j] + s[i,j-1] - S[i-1,j-1] + a[i,j](表示当前的数)以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:S[x2, y2] - S[x1-1,y2] - S[x2,y1-1] + S[x1-1,y1-1]二维前缀和理解:第一步:如何计算S[i, j]?如下图可以知道,我们要求蓝色的S[3, 4],那么可以知道可以等于绿色S[2, 4]、原创 2022-04-24 20:19:13 · 4820 阅读 · 3 评论 -
基础算法:一维前缀和
一维前缀和C++模板:S[i] = a[1] + a[2] + ... a[i]a[l] + ... + a[r] = S[r] - S[l - 1]一维前缀和理解:s[ i ] 就是前 i 个数的和作用:可以很快速求出原数组某一段的和,比如[l,r]区间的和就是s[r]-s[l-1]注意:下标尽量从1开始,这样可以定义s[ 0 ],去掉边界问题。比如:如果求[ 1 , k ]的和,那么如果下标从0开始,那么s[ k -1] - s[ 0 -1 ]会越界题目: AcWing 795. 前缀原创 2022-04-23 21:50:19 · 169 阅读 · 0 评论 -
基础算法:高精度除法
高精度除以低精度C++模板:注意:A是高精度,b是低精度容器A保存的是数字的逆序(低位在前)计算时是先计算高位,所以要从后往前计算(保存的是逆序)// A / b = C ... r, A >= 0, b > 0vector<int> div(vector<int> &A,int b,int &r){ vector<int> C; r=0; for(int i=A.size()-1;i>=0;i--)原创 2022-04-23 17:39:33 · 400 阅读 · 0 评论 -
基础算法:高精度乘法
高精度乘低精度C++模板:注意:A是高精度,b是低精度vector<int> mul(vector<int> &A,int b){ vector<int> C; int t=0; for(int i=0;i<A.size()||t;i++) { if(i<A.size())t+=A[i]*b; C.push_back(t%10); t/=10; } r原创 2022-04-23 17:12:31 · 1175 阅读 · 0 评论 -
基础算法:高精度减法
高精度减法C++模板:注意:容器A,B保存的是数字的逆序(低位在前)用sub时保证A>B,这样更好计算//判断A和B的长度,如果A长返回true,否则返回falsebool cmp(vector<int> &A,vector<int> &B){ if(A.size()!=B.size())return A.size()>B.size(); for(int i=A.size()-1;i>=0;i--) if(原创 2022-04-23 16:45:05 · 177 阅读 · 0 评论 -
基础算法:高精度加法
高精度加法C++模板:注意:容器A,B保存的是数字的逆序(低位在前)vector<int> add(vector<int> &A,vector<int> &B){ vector<int> C; int t=0; for(int i=0;i<A.size()||i<B.size();i++) { if(i<A.size())t+=A[i]; if(i<B原创 2022-04-23 15:50:06 · 225 阅读 · 0 评论 -
基础算法:数的三次方根—浮点二分
浮点二分C++模板:bool check(double x) {/* ... */} // 检查x是否满足某种性质double bsearch_3(double l, double r){ const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求 while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) r = mid;原创 2022-04-22 21:29:25 · 296 阅读 · 0 评论 -
基础算法:数的范围—整数二分
整数二分C++模板:注意:如果是l=mid需要mid=(l+r+1)/2,这样保证不会死循环这种二分最后肯定会得到一个结果bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:int bsearch_1(int l, int r){ while (l < r) { int mid = l + r >> 1; if (原创 2022-04-22 21:05:21 · 99 阅读 · 0 评论 -
基础算法:逆序对的数量—归并排序
题目:给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。输入格式:第一行包含整数 n,表示数列的长度。第二行包含 n 个整数,表示整个数列。输出格式:输出一个整数,表示逆序对的个数。数据范围:1≤n≤100000,数列中的元素的取值范围 [1,109]。输入样例:62 3 4 5 6 1输出样例:5做题思路:假设me原创 2022-04-22 13:31:40 · 377 阅读 · 0 评论 -
基础算法:归并排序
归并排序C++模板:注意:需要用到辅助数组,帮助两个部分进行合并时的结果保存int q[N],tmp[N];void merge_sort(int q[],int l,int r){ if(l>=r)return; int mid=l+r>>1; merge_sort(q,l,mid); merge_sort(q,mid+1,r); int i=l,j=mid+1,k=0; while(i<=mid&&j<原创 2022-04-21 21:49:52 · 434 阅读 · 0 评论 -
基础算法:第k个数—快速排序
题目: 第k个数给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。输入格式:第一行包含两个整数 n 和 k。第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整数数列。输出格式:输出一个整数,表示数列的第 k 小数。数据范围:1≤n≤100000,1≤k≤n输入样例:5 32 4 1 5 3输出样例:3题目分析:简单做法就是使用排序算法直接排序,如何输出第k个数即可。下面我们从快速排序找到灵感:快原创 2022-04-21 20:50:51 · 315 阅读 · 0 评论 -
基础算法:快速排序
快速排序C++模板:注:1. i和j为啥取l-1,和r+1 因为后面使用do-while循环首先两个下标都会移动(方便当有相等时,下一次两个下标的移动)2.x基准数为啥取中间,因为取首和尾很容易出现越界问题,造成死循环3.两个区间为啥是l~j和j+1~r,因为i和j其实都是指向的本区间的下一个下标,因为do-while循环的缘故void quick_sort(int p[],int l,int r){ if(l>=r)return; int i=l-1,j=r+1,x=p[原创 2022-04-21 20:06:23 · 248 阅读 · 0 评论