基础算法

排序

快速排序

思想:分治

  1. 确定分界点:q[l],q[(l+r)/2],q[r]
  2. 调整范围:q[]<=x,q[]>=x
  3. 递归处理左右两段
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
//不能令 mid=l+r>>1 因为 q[mid] 可能会被交换
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j);
//用 j 做边界时,x 不能取 q[r]; 用 i 做边界时,x 不能取 q[l] (stagement fault)
quick_sort(q, j + 1, r);
}

归并排序

分治

  1. 确定分界点 mid=(l+r)/2
  2. 递归排序左右两边
  3. 归并:合二为一
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 k=0,i=l,j=mid+1;
while(i<=mid&&j<=r)
if(q[i]<=q[j]) temp[k++]=q[i++];
else temp[k++]=q[j++];
while(i<=mid) temp[k++]=q[i++];
while(j<=r) temp[k++]=q[j++];
for(i=l,j=0;i<=r;i++,j++) q[i]=temp[j];
}

二分

整数二分

  1. 本质:边界,某一性质在左半边满足,在右半边不满足
  2. 步骤
    1. mid二分,判断mid点是否满足
    2. 选择区间,判断是否包括边界
    3. 递归得到答案
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 (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}

浮点数二分

不需处理边界

bool check(double x) {/* ... */} // 检查 x 是否满足某种性质
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)//也可以写 for(int i=0;i<100;i++) ,即将范围除以 2^100 ,精度足够高
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}

高精度

输入输出

string a,b;
vector<int>A,B;
cin>>a>>b;//a="123456"
for(int i=a.size()-1;i>=0;i--)
A.push_back(a[i]-'0');//A = [6,5,4,3,2,1]
for(int i=b.size()-1;i>=0;i--)
B.push_back(b[i]-'0'); auto C=add(A,B);
for(int i=C.size()-1;i>=0;i--)
printf("%d",C[i]);

高精度加法

vector<int> add(vector<int> &A, vector<int> &B)
{
if (A.size() < B.size()) return add(B, A);
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++ )
{
t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(t);
return C;
}

高精度减法

bool 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(A[i]!=B[i])
return A[i]>B[i];
return true;
}
vector<int> sub(vector<int> &A, vector<int> &B)
{
if(!cmp(A,B))
{
cout<<"-";
return sub(B,A);
}
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i ++ )
{
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}

高精度乘法

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;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}

高精度除法

vector<int> div(vector<int> &A, int b, int &r)//高精除低精
{
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i -- )
{
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}//aaaaa/bb=00cdef
reverse(C.begin(), C.end());//fedc00
while (C.size() > 1 && C.back() == 0) C.pop_back();//fdec
return C;
}

前缀和

前缀和:\(S_i=a_1+a_2+...a_i\)

for(i=1;i<=n;i++)//求前缀和
S[i]=S[i-1]+a[i];
cin>>a>>b;cout<<S[b]-S[a-1]<<endl;//算部分和
  • \(\sum_{i=a}^b{a_i}=S_b-S_{a-1}\)

  • 前缀和能快速计算区间和a[l]~a[r],累加复杂度O(n) ,而前缀和复杂度O(1)

  • 首项为\(a_1\)能更好地处理边界问题,令\(S_0=0\),则\(\sum_{i=1}^n{a_i}=S_n-S_0\)

二维前缀和:\(S_{x,y}=\sum_{i=1}^x{\sum_{j=1}^y{a_{i,j}}}\)

for(int i=1;i<=n;i++)//求前缀和
for(int j=1;j<=m;j++)
S[i][j]=S[i-1][j]+S[i][j-1]-S[i-1][j-1]+a[i][j];
cin>>x1>>y1>>x2>>y2;
cout<<S[x2][y2]-S[x1-1][y2]-S[x2][y1-1]+S[x1-1][y1-1]<<endl;//算部分和
  • \(\sum_{i=x_1}^{x_2}{\sum_{j=y_1}^{y_2}{a_{i,j}}}=S_{x_2,y_2}-S_{x_2,y_1-1}-S_{x_1-1,y_2}+S_{x_1-1,y_1-1}\)

差分

前缀和的逆运算

差分:构造\({\{b_n\}}\)使得\(a_n=\sum_{i=1}^n{b_i}\),即\(b_i=a_i-a_{i-1}\),则\({\{b_n\}}\)为\({\{a_n\}}\)的差分,\({\{a_n\}}\)为\({\{b_n\}}\)的前缀和

  • 差分能快速进行区间更新,将复杂度从O(n)降到O(1)
//为区间 [l,r] 的所有元素加上 c
B[l]+=c;B[r+1]-=c;
//通过差分求原数列
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1];
cout<<b[i];
}

二维差分:\(b_{i,j}=a_{i,j}-a_{i-1,j}-a_{i,j-1}+a_{i-1,j-1}\)

//为区间 (x1,y1) 到 (x2,y2) 的所有元素加上 c
B[x1,y1]+=c,B[x2+1,y1]-=c,B[x1,y2+1]-=c,B[x2+1,y2+1]+=c;
//通过差分求原数列
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1];
cout<<b[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
cout<<b[i][j]<<" ";
}
cout<<endl;
}

双指针算法

  1. 核心思想:两个指针同时操作数据结构,将复杂度从\(O(n^2)\)降至\(O(n)\)
for(i=0,j=0;i<n;i++)
{
while(j<i&&check(i,j)) j++;
//每道题具体逻辑
}

位运算

n>>k&1;//n 的二进制表示的第 k 位
for(int k=n;k>=0;k--) cout<<(n>>k&1);//转换为二进制表示
lowbit(x)=x&-x;//返回 x 的最后一位 1
while(x) x -=(x & -x),tot++;//统计 x 中 1 的个数

离散化

将大范围数据映射到小范围数据

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;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1; // 映射到 1, 2, ...n
}

区间合并

快速合并有交集的区间

  1. 按区间左端点排序
  2. 从左往右维护区间,若下一区间左端点小于等于该区间右端点,归并区间;若下一区间左端点大于等于该区间右端点,纳入答案
typedef pair<int,int> PII;
const int M = -2e9;//边界
void merge(vector<PII> &segs)
{
vector<PII> res;
sort(segs.begin(), segs.end());
int st = M, ed = M;
for (auto seg : segs)
if (ed < seg.first)
{
if (st != M) res.push_back({st, ed});
st = seg.first, ed = seg.second;
}
else ed = max(ed, seg.second);
if (st != M) res.push_back({st, ed});
segs = res;
}

0x01 基础算法的更多相关文章

  1. PHP基础算法

    1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++ ...

  2. 10个经典的C语言面试基础算法及代码

    10个经典的C语言面试基础算法及代码作者:码农网 – 小峰 原文地址:http://www.codeceo.com/article/10-c-interview-algorithm.html 算法是一 ...

  3. Java基础算法集50题

    最近因为要准备实习,还有一个蓝桥杯的编程比赛,所以准备加强一下算法这块,然后百度了一下java基础算法,看到的都是那50套题,那就花了差不多三个晚自习的时间吧,大体看了一遍,做了其中的27道题,有一些 ...

  4. 贝叶斯公式由浅入深大讲解—AI基础算法入门

    1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大.而且概率虽然未知,但最起码是一个确定 ...

  5. 贝叶斯公式由浅入深大讲解—AI基础算法入门【转】

    本文转载自:https://www.cnblogs.com/zhoulujun/p/8893393.html 1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生, ...

  6. java入门学习(3)—循环,选择,基础算法,API概念

    1.顺序结构:也就是顺着程序的前后关系,依次执行.2.选择分支:利用if..else , / switch(){case [ 这个必须是常量]:}; / if..else if….. ….else.. ...

  7. Java - 冒泡排序的基础算法(尚学堂第七章数组)

    /** * 冒泡排序的基础算法 */ import java.util.Arrays; public class TestBubbleSort1 { public static void main(S ...

  8. c/c++面试总结---c语言基础算法总结2

    c/c++面试总结---c语言基础算法总结2 算法是程序设计的灵魂,好的程序一定是根据合适的算法编程完成的.所有面试过程中重点在考察应聘者基础算法的掌握程度. 上一篇讲解了5中基础的算法,需要在面试之 ...

  9. c/c++面试指导---c语言基础算法总结1

    c语言基础算法总结 1  初学者学习任何一门编程语言都必须要明确,重点是学习编程方法和编程思路,不是学习语法规则,语法规则是为编程实现提供服务和支持.所以只要认真的掌握了c语言编程方法,在学习其它的语 ...

  10. ACM基础算法入门及题目列表

    对于刚进入大学的计算机类同学来说,算法与程序设计竞赛算是不错的选择,因为我们每天都在解决问题,锻炼着解决问题的能力. 这里以TZOJ题目为例,如果为其他平台题目我会标注出来,同时我的主页也欢迎大家去访 ...

随机推荐

  1. spring-springMVC-总结列表

    Spring 的优良特性 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API 控制反转:IOC--Inversion of Control,指的是将对象的创建权交给 Spri ...

  2. iScroll4中事件点击一次却触发两次解决方案

    iScroll是我们在做手机网页中常用的滑动控件之一.单说其功能已相当丰富.但个别时候也是会掉坑的,正好这次就遇上了.在android的app中嵌入网页时不少手机会出现一次点击两次触发的现象.经过一段 ...

  3. 《Linux shell 脚本攻略》第1章——读书笔记

    目录 文件描述符及重定向 函数和参数 迭代器 算术比较 文件系统相关测试 字符串进行比较 文件描述符及重定向 echo "This is a sample text 1" > ...

  4. 让你看懂dart中静态成员和继承

    静态属性和静态方法 在dart中,我们可以通过关键字 static来定义静态属性和静态方法. 需要注意的是: 静态方法不能访问非静态属性[结论1] 非静态方法可以访问静态成员[结论2] 我们通过下面的 ...

  5. nginx 编译安装及配置解析

    一.编译安装 安装插件 安装需要的组件 yum -y install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel ...

  6. 表治理-Iceberg元数据合并-metadata.json文件

    一.背景描述 元数据文件随时间增多,导致查询变慢.通过如下方式可以指定metadata个数,超过指定数量自动清理. metadata文件对应Iceberg概念是Snapshots 二.解决方案 1.在 ...

  7. NOIp 2024 考试策略

    无论简不简单,都要在前 30min 浏览所有题面,思考哪题可做.哪题不可做,思考能打哪些部分分,9:00 再开始写 T1. 题目简单时 9:00 开写后,30min 以内切完 T1. 9:30 开 T ...

  8. LLM探索:离线部署Ollama和one-api服务

    前言 之前已经在Linux服务器上使用Ollama部署了DeepSeek 这次在没有外网(应该说是被限制比较多)的服务器上部署,遇到一些坑,记录一下 ollama ollama 自然无法使用在线安装脚 ...

  9. ABB机器人伺服电机维修有脉冲输出时不工作怎么处理

    1.ABB机器人伺服电机维修有脉冲输出时不工作怎么处理? 监督操控器的脉冲输出当时值以及脉冲输出灯是否闪烁,承认指令脉冲现已履行并现已正常输出脉冲:查看操控器到驱动器的操控电缆,动力电缆,编码器电缆是 ...

  10. AWS - [01] 概述

    题记部分 001 || 概述   AWS,全称Amazon Web Services,是亚马逊公司旗下的云计算服务平台,自2006年起向全球用户提供广泛而深入的云计算服务.AWD是全球最全面.应用最广 ...