高效定制算法

本文探讨了算法分析的重要性,详细解释了归并排序的原理和二分思想的应用。通过实例展示了如何运用构造法、中途相遇法、问题分解法等策略设计算法,还提到了滑窗法、最大值尽量小、优先队列和简单递归等技巧在解决实际问题中的应用。
摘要由CSDN通过智能技术生成

一般来说:
n<=8时,n的阶乘运算量算法就够了(排列枚举)
n<=20时,用到2^n运算量算法(子集枚举)
n<=300至少用n的三次方运算量算法
大O 大theta
不需要进行精确地分析,假定各种最坏情况同时取到得到上界,这就是大O表示法。

算法分析

用心体会左闭右开区间的使用方法,显得非常自然,[X,X)代表空区间。
[X,Y)程序中根本不会用到y位置,相当于一个结束符位置。
在处理数组分割时非常好用

         递归子问题个数
T(n)     =  2*T(n/2)       +      O(n)
问题规模      递归子问题规模       合并时间
时间复杂度为O(nlgn)

示例:连续子序列最大和问题可以优化为子序列的尾部的前j项之和与子序列的首部的前i项之和的差。注意减法的时候,被减数会被减掉。

int s[0]=0,best=A[1];
for(int i=1;i<=n;i++) s[i]=s[i-1]+A[i];//保存前i项的和
for(int i=1;i<=n;i++)//遍历所有的子序列
   for(int j=i;j<=n;j++)
     best=max(best,s[j]-s[i-1]);
      此时时间复杂度就变为了O(n^2);     

归并排序 O(nlgn)

对一个数列分两半,分别递归,当只有两个元素时递归结束,然后进行一般化合并处理。合并不是单纯的对两个子数列进行比较,而是每次取数列中的最小值先比较把小的数字删除并放入到新表中,大的数按原位保持不变。所以有可能在一个子数列中取多次值,只要两个子数列有一个不为空时就能放数字到新表中,采取短路运算符"||"(先判断第一个条件,判断第二个条件的前提是第一个条件不满足),然后再进行放入新表操作。
放入的新表只是当前递归的一个辅助空间,存放排好的序列,注意当前递归结束时一定要把新表赋值给原表,因为上一级栈帧需要使用已经排序好的表,这也是合并的精髓。

void mergesort(int* A,int* T,int x,int y)
{
   
    //排序为左闭右开区间[x,y)
    //直接输出A即可,T是一个辅助空间
    if(y-x >1){
   
        int m=x+(y-x)/2;
        int p=x,q=m,i=x;
        mergesort(A,T,x,m);
        mergesort(A,T,m,y);
        while(p<m || q<y)
        {
   
        //分三种情况讨论  1空2非 1非2空 1非2非
        //1非2空 1非2非为一种情况,进行合并,q>=y时说明1非2空
        if(q>=y || (p<m && A[p]<=A[q]) ) T[i++]=A[p++];
        else
            T[i++]=A[q++];
        }
        for(i=x;i<y;i++)A[i]=T[i];//注意这里,每次都要更新A的值来对下一次递归使用
     }
}

二分思想 O(lgn)

一般写成非递归形式

二分返回第一个查找到的值,查找区间为左闭右开区间
int bsearch(int* A,int x,int y,int v)
{
   
int m;
while(x<y){
   
m=x+(y-x)/2;
if(A[m]==v) return m;
else if(A[m]>v) y=m;
else x=m+1;
}
return -1;
}

二分查找只适用于有序序列,但是二分的思想常常用在一些抽象的场合。

左闭右开区间,二分返回查找到的下界,当v存在时返回他出现的第一个位置
int bsearch(int* A,int x,int y,int v)
{
   
int m;
while(x<y){
   
m=x+(y-x)/2;
if(A[m]>=v) y=m;
else x=m+1;
}
return x;
二分返回查找到的上界,当v存在时返回出现的最后一个位置的后面一个位置
int bsearch
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值