zoukankan      html  css  js  c++  java
  • 最大子序列和问题

    1.递归

    该方法由书上提供,比较好理解:给定一个数组,从中间划分成两个数组[1,mid],[mid+1,end];最大子序列可分为三种情况:

    a.位于左半边

    b.位于右半边

    c.跨越两边

    求两边最大子序列时可递归求解,求跨越两边的子序列时分别从mid、mid+1出发,求得left_sum和right_sum,相加即为跨越两边的最大子序列和。时间复杂度O(nlogn)。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int Find_Mid_Max(int* q,int start,int end) {
        int mid = (start + end) / 2;
        int left_sum = 0;
        int right_sum = 0;
        int sum = 0;
        int i;
        for (i = mid;i > 0;i--) {
            sum += q[i];
            if (sum > left_sum)
                left_sum = sum;
        }
        sum = 0;
        for (i = mid+1;i <=end;i++) {
            sum += q[i];
            if (sum > right_sum)
                right_sum = sum;
        }
        return left_sum + right_sum;
    }
    
    int Find_Max(int* q, int start, int end) {
        int maxsum = 0;
        if (start == end) {
            if (q[end] > maxsum)
                maxsum = q[end];
            return maxsum;
        }
        int mid = (start + end) / 2;
        int left=Find_Max(q, start, mid);
        int right = Find_Max(q, mid + 1, end);
        int across = Find_Mid_Max(q, start, end);
        if (left > right && left > across)
            maxsum = left;
        else if (right > across)
            maxsum = right;
        else
            maxsum = across;
        return maxsum;
    }
    
    int main() {
        int k;
        if (scanf("%d", &k) == 0){}
        int* q = (int*)malloc(sizeof(int) *(k+1));
        int i;
        for (i = 1;i <= k;i++) {
            if(scanf("%d",&q[i])==0){}
        }
        int max=Find_Max(q, 1, k);
        printf("%d", max);
        return 0;
    }

     2.在线处理

    从第一个元素开始遍历整个数组,用tempsum暂时记录当前子序列的和。如果加上一个元素之后,tempsum<0了,那么包含这个元素再继续往后加的子序列一定不可能是最大的,因为负数总是对这个子序列产生消极的影响,所以我们可以舍弃这个序列,从下一个序列开始再次寻找。用maxsum记录最大值,若tempsum>maxsum则更新。还要记录最大子序列的开始和结束点(具体见代码,有些地方是题目里要求的)。时间复杂度O(n)。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int* Find_Max(int* q, int start, int end) {
        int *ret=(int *)malloc(sizeof(int)*3);
        ret[0] = 0;//记录最大和
        ret[1] = start;//开始下标
        ret[2] = 0;//结束下标           
        int tempsum = 0;
        int temps = 0;
        int i;
        int neg = 0;
        int pos = 0;
        int zer = 0;
        for (i = 0;i < end;i++)  {
            if (q[i] > 0)
                pos = 1;
            if (q[i] < 0)
                neg = 1;
            if (q[i] == 0)
                zer = 1;
            tempsum += q[i];
            if (tempsum < 0) {
                tempsum = 0;
                temps = i + 1;
            }
            else {
                if (tempsum > ret[0]) {
                    ret[0] = tempsum;
                    ret[1] = q[temps];
                    ret[2] = q[i];
                }
            }
        }
        if (!pos&&neg&&!zer) {
            ret[1] = q[start];
            ret[2] = q[end-1];
        }
        else if (!pos && neg && zer) {
            ret[1] = start;
            ret[2] = 0;
        }
        return ret;
    }
    
    int main() {
        int k;
        if (scanf("%d", &k) == 0){}
        int* q = (int*)malloc(sizeof(int) *k);
        int i;
        for (i = 0;i < k;i++) {
            if(scanf("%d",&q[i])==0){}
        }
        int *ret=Find_Max(q, 0, k);
        printf("%d %d %d", ret[0],ret[1],ret[2]);
        return 0;
    }
  • 相关阅读:
    JAVA数据库建表工具类
    HTML加CSS3太极图demo
    MD5加密(JAVA&JS)
    Base64工具类(JAVA&JS)
    JS模拟圆周运动
    JAVA读取写入excle表兼容版
    Math.PI和Math.sin() 与 Math.cos()搭配使用详解
    MySQL8.0数据库连接问题
    echarts饼状图案例
    JS前端使用MD5加密
  • 原文地址:https://www.cnblogs.com/yaotong0830/p/14192648.html
Copyright © 2011-2022 走看看