C/C++语法基础
这个这里不讲了,网上的教学很全面详细
时间复杂度与空间复杂度
空间复杂度一般情况下我们不考虑、因为在算法比赛中一般会给你很大的空间,稍微注意即可,不要有开过于庞大的数组或忘了释放内存之类的操作即可
我们这里主要讨论时间复杂度
那么什么是时间复杂度,其实通俗讲就是程序的运行时间(用来衡量算法快慢)
比如我们执行a+b的操作,程序只执行了一次,那么我们将这一次时间称为O(1)
执行a+b+c那么就将时间称为O(2)
如果执行a+b+............+n+1的话 程序总共执行了n次,类比极限的思想我们就可以得出这个程序运行的时间是O(n)
在我们算法的运行中,我们一般只考虑这个算法所耗时间最长最坏的情况,这个最长的情况就是你这个算法的时间复杂度
而在实际中我们计算时间复杂度时,我们不用计算精确的程序运行次数,得出大概的数即可
比如像什么a+b、a*c+d/e-g这种的,能基本数过来的我们统一用O(1)表示 ,意思是这个算法的时间复杂度是常数级别O(1)
要是数不过来我们就需要简单估计一下了
比如我们有一个数组1、2、3、4、............n
我们想用顺序查找第n个数,如果我们想找第一个数,那么找一次就行了,此时时间复杂度为O(1)
但如果我们想找第n个数,那么我们一共要找n次,此时时间复杂度就是O(n)
时间复杂度排序如下Ο(1)<Ο(log n)<Ο(n)<Ο(nlog n)<Ο(n^2)<Ο(n^3)<......<Ο(2^n)<Ο(n!)
读题时,通过给的样例的规模来快速判断我们大概需要多少时间复杂度的算法
若数据规模给的10^6以内,那么用O(n)算法即可解决、若给的1000以内、用O(n²)即可解决
如果数据规模给的很大比如10^20,那么就需要我们想出O(log n)的算法了
对数器
这个对数不是指的数学上log那个对数、也有叫对拍器的,这个对数是指:对 正确答案 数
对数器是一种思想
我们在比赛中可能对于大多数问题,我们能很好的用暴力解决来想到题解,但是往往会超出时间限制,所以我们需要找到对应的算法来解决。但是我们敲的算法不一定能过所有样例点,即它不一定是对的,这个时候就需要用到对数器了
对数器本质是一个样例的随机生成器,就是你自己拟题目给的样例点,然后对比暴力解的答案和优化解的答案是否一致,假如你自己拟了100组样例,暴力解和优化解的答案全部一样,那么我们就可以初步判断写的算法是对的
可以类比演绎,即从一般到特殊、构造对数器是检查我们写的算法是否正确的一个有效手段。
三个基础排序
很多举例都会用这三个排序、这三个简单的排序能帮你快速明白啥是算法
选择排序(基本用不到)
在0~n上找到第i小的数并与第i个位置交换
void selectionSort(vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n - 1; ++i) {
int minIndex = i;
for (int j = i + 1; j < n; ++j) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
swap(arr[i], arr[minIndex]);
}
}
冒泡排序(也基本用不到)
在0~n上,相邻两数比较并交换
void bubbleSort(vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - 1 - i; ++j) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
}
}
}
}
插入排序(比较常用)
有的时候还能碰瓷一下高级排序算法
在0~n上,不断的把新数插入到已经排序好的数组里
void insertionSort(vector<int>& arr) {
int n = arr.size();
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
二分搜索
最最最最常用的算法 用二分的首要前提是数组是排序好的
找数组中是否有某个数
每次找数组中间的数
如果数组中间的数比要找的数大
那么要找的数肯定在中间的数左边
如果数组中间的数比要找的数小
那么要找的数肯定在中间的数右边
int binarysearch(vector<int>&arr,int n){
int l=0,r=arr.size()-1,m=0;
while(l<=r) {
m=(l+r)/2;
if(arr[m]==n)return m;
else if(arr[m]>n)r=m-1;
else l=m+1;
}
return -1;
}
找大于等于某个数的第一个数的索引
跟上面一样的思想
int binaryfindsearch(vector<int>&arr,int n){
int l=0,r=arr.size()-1,m=0,ans=-1;
while(l<=r) {
m=(l+r)/2;
if(arr[m]>=n) {
ans=m;
r=m-1;
}
else l=m+1;
}
return ans;
}
找小于等于某个数的第一个数的索引
同上
#include<bits/stdc++.h>
using namespace std;
int binaryfindsearch(vector<int>&arr,int n){
int l=0,r=arr.size()-1,m=0,ans=-1;
while(l<=r) {
m=(l+r)/2;
if(arr[m]<=n) {
ans=m;
l=m+1;
}
else r=m-1;
}
return ans;
}
后续有习题会更新