紫书第八章

一、分治法

1.最大连续和

题意:给出一个长度为n的序列A1,A2,...An,求最大连续和。换句话说就是要求找到1<=i<=j<=n,使得Ai+Ai+1+...+Aj最大

代码:

int maxSum(int *A,int x,int y){//返回数组在左闭右开区间[x,y)中的最大连续和
    int v,l,r,maxs;
    if(y-x==1) return A[x];   //只有一个元素,直接返回
    int m = x + (y-x)/2; //分治第一步,划分为[x,m)和[m,y)
    maxs = max(maxSum(A,x,m),maxSum(A,m,y));//分治第二步:递归求解
    v=0;l=A[m-1];
    for(int i=m-1;i>=x;i--) l = max(l,v+=A[i]); // 分治第三步:合并(1)——从分界点开始往左的最大连续和L
    v=0;r=A[m];
    for(int i=m;i<y;i++) r = max(r,v+=A[i]);//分治第三步:合并(2)——从分界点往右的最大连续和R
    return max(maxs,l+r);//把子问题的解L和R比较
}

2.归并排序

代码:

int cnt = 0;求逆序数
void merge_sort(int *A,int x,int y,int *T){
    if(y-x>1){
        int m = x + (y-x)/2;//划分
        int p = x,q = m,i = x;
        merge_sort(A,x,m,T); //递归求解
        merge_sort(A,m,y,T); //递归求解
        while(p<m||q<y){
            if(q>=y||(p<m&&A[p]<=A[q]))
                T[i++] = A[p++];//从左半数组复制到临时空间
            else{
                T[i++] = A[q++];//从右半数组复制到临时空间
                cnt+=m-p;//这里“顺便”求逆序数
            }
        }
        for(int i=x;i<y;i++) A[i]=T[i];//从辅助空间返回A数组
    }
}

3.快速排序

代码:

void q_sort(int *a,int _left,int _right){

    int i = _left ;
    int j = _right;
    int temp = a[_left];
    if(_left>=_right) return;
    while(i!=j){
        while(i<j&&a[j]>temp)
            j--;
        if(j>i) a[i] = a[j];
        while(i<j&&a[i]<=temp)
            i++;
        if(i<j) a[j] = a[i];
    }
    a[i] = temp;
    q_sort(a,_left,i-1);
    q_sort(a,i+1,_right);
}

4.二分查找

4.1 找一个数

代码:

void binarySearch(int num[],int len,int key)
{
    int index1 = 0,index2 = len-1;
    while(index1<=index2)
    {
        if(key==num[(index1+index2)/2])
        {
            cout<<"find"<<endl;
            return;
        }else if(key<num[(index1+index2)/2])
        {
            index2 = (index1+index2)/2 -1;
        }else
        {
            index1 = (index1+index2)/2 +1;
        }
        cout<<index1<<" "<<index2<<endl;
    }
    cout<<"not found"<<endl;
}

4.2求一个数第一个出现的位置(lower_bound())

代码:

//这个算法中,first是最终要返回的位置
int lower_bound(int *array, int size, int key)
{
    int first = 0, middle;
    int half, len;
    len = size;


    while(len > 0) {
        half = len >> 1;
        middle = first + half;
        if(array[middle] < key) {     
            first = middle + 1;          
            len = len-half-1;       //在右边子序列中查找
        }
        else
            len = half;            //在左边子序列(包含middle)中查找
    }
    return first;
}

4.3求一个数最后出现的位置

代码:

int upper_bound(int *array, int size, int key)
{
    int first = 0, len = size-1;
    int half, middle;

    while(len > 0){
        half = len >> 1;
        middle = first + half;
        if(array[middle] > key)     //中位数大于key,在包含last的左半边序列中查找。
            len = half;
        else{
            first = middle + 1;    //中位数小于等于key,在右半边序列中查找。
            len = len - half - 1;
        }
    }
    return first;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值