基础算法鸭

1.归并

归并,分治。两者概率模糊。有父子的关系。

归并用递归去实现

‘分’是为了方便‘治’,‘治’有助于‘归’

void fun(...){
	终止条件;
	分;
	治;
	归;
}
归并排序
int a[maxn];//待排序数组
int p[maxn];//拷贝数组
void fun(int f,int l){	//函数参数用数组也可以 ,没必要,数组当参数无所谓的 不用考虑爆栈、传过来的是一个地址指针
    if(f==l) return ;//终
  
    int mid=f+l>>1;//分
    fun(f,mid),fun(mid+1,l);
  
    int i=f,j=mid+1,k=0;//治
    while(i<=mid&&j<=l){
        if(a[i]<a[j]){
            p[k++]=a[i++];
        }else{
            p[k++]=a[j++];
        }
    }
    while(i<=mid){p[k++]=a[i++];}
    while(j<=l){p[k++]=a[j++];}


    for(i=0,j=f;i<k;i++,j++){//归
        a[j]=p[i];
    }
}

二分

二分查询的东西首先要满足某种规律。多见于对于答案二分。

二分困难的点在于对边界的判断,cheack函数时 <= >=

二分的思路其实像一种数字游戏:

A在纸上写了一个1到100之内任意的一个数,B去猜

B猜50,A回答大了

B猜25,A回答小了

B猜34,。。。。。

至于模板有三种。。。。前两种来自闫总模板,后面一种是李秉庚的模板。

//[f,mid][mid+1,l]
int fun(int f,int l){
    int mid;
    while(f<l){
        mid=f+l>>1;
        if(check(mid)){
            f=mid+1;
        }else{
            l=mid;
        }
    }
    return f;
}
//[f,mid-1][mid,l]
int fun(int f,int l){
    int mid;
    while(f<l){
        mid=f+l>>1;
        if(check(mid)){
            f=mid;
        }else{
            l=mid-1;
        }
    }
    return f;
}

int fun(int f,int l){
    int mid;
    while(f<=l){
        mid=f+l>>1;
        if(check(mid)){
            f=mid+1;
        }else{
            l=mid-1;
        }
    }
    return l;
}

高精度

这个不是算法,是最基本的代码实现能力,不说。

前缀和差分

对于前缀和

结合高中前缀和的知识。

对于一个数组

a1,a2,a3,a4,a5。。。。

s1=a1

s2=a1+a2

s3=a1+a2+a3

s4=a1+a2+a3+a4

s5=a1+a2+a3+a4+a5

不难推出 a4=s4-s3;

在程序里面也存在这样的事实。

前缀和是一种思想,他没有牺牲空间,直接让查询时间变成O(1)

对于差分

差分和前缀和相对。

对于上面的例子 S是A的前缀和数组,那么A就是S的差分数组。

差分使用的地方。。。对前缀和数组倒过来想、是在对一段数组进行操作。

至于代码,不至于给出了

双指针算法

双指针算法的理解一直是很模糊的概率,双指针?像归并中的i,j。
但其实这一类算法,不是算法,还是思想。

写出最朴素的算法,优化朴素

位运算

二进制是计算机最朴素的公民。至少目前位置。01加上定义的规则,01就是整个世界。

状态压缩

0和1可以表达逻辑真假。bool就是这么干的。但是bool浪费了3个位的0!!!!

那么一个longlong可以记录64个人的状态。

快速幂

这里不太想把快速幂和状态压缩分开讲,位运算版的快速冥其实就是记状态。

假设一个2^7次方可以写成

2 ^ 4 * 2 ^ 2 * 2 like (4+2+1)

二进制可以表达任意的数字。所以能用次方的位来判断ans结果需不需要乘上当前数。

当前数即上一个数的平方 不要问我初始化。最初状态、边界 永远是一件神器的事情。也许就像刚开始学背包问题。

int fun(int a,int b){//a^b
    int ans=1;
    while(b){
        if(b&1) ans*=a;
        a * = a;
        b >> =1;
    }
    return ans;
}

离散化、区间合并

把不连续的东西连续起来 ,比如一个数组t[]

t[1]和t[11111]存了东西 ,但是1到11111之间都没有元素,这中间的查询时白浪费的 ,如果是一些 不想桶排那样的 可以直接压缩数组t

让t[1]之后链接的元素就是t[11111]

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值