《主要解析分治法——数列最大子段和》

​​​​​​​一、思路 (给定n个元素的整数列)

以数组的 center = (right-left)/2 位置处分开。形成两个子数组。

那么,最大子段和 可能出现在三个位置:

1.可能出现在 left子数组 ——>a[1,(n/2)]

2. 可能出现在 right子数组——>a[(n/2)+1,n)]

3.可能出现在 过center的 中间某部分 元素 组成的子数组

p表最左位置

q表最右位置

——>a[p,q]即1=<p=<n/2 , n/2+1=<q=<n

下面考虑 三种情况的计算方法:

第一种情况: 计算 left 到 center 的最大和,记作 left_sum

第二种情况: 计算从 center+1 到 right的最大和,记作 right_sum

第三种情况: 跨边界的和。 以center为中心分别向两边计算和。

1.从 center出发,每次向左边遍历一次,就累加到lefts,如果当前的和比上次的和大,就赋给s1,一直向左直到位置 left。

2.从 center+1出发,每次向右边遍历一次步,就累加到rights,如果当前的值比上次的和 大,就赋给s2,一直向右直到位置right。

3.计算过center的连续值的和,s1+s2的和值 , 这个就是跨边界的和。

上面三种情况考虑计算完成后,最后一步就是,比较三个值中的最大值,取最大值即可。

算法一、算法二和算法四就不过多叙述了直接引用了,其大致内容都差不多

算法一部分代码:T(n)=O(n^2)

算法二部分代码:

算法四部分代码:

图例:

二、算法3代码展示

#include<stdio.h>
#include<stdlib.h>
#define N 100010
//#include<bits/stdc++.h>
//using namespace std;

int max_sum(int a[],int n)
{
   return max_sub_sum(a,1,n);
}
int max_sub_sum(int a[],int left,int right)
{
    int center,i,left_sum,right_sum,s1,s2,lefts,rights;
    if(left==right)
    {
        if(a[left>0]) return a[left];
        else return (0);
    }else{
        center=(left+right)/2;
        left_sum=max_sub_sum(a,left,center);// 左边最大子段
        right_sum=max_sub_sum(a,center+1,right);// 右边最大子段
    }
    //求中间最大子段
    s1=0;lefts=0;
    for(i=center;i>=left;i--)
    { // 注意:这里是从中间向左遍历,目的是为了让划分的左右两边序列能连接起来
        lefts+=a[i];
        if(lefts>s1) s1=lefts;
    }
    s2=0;rights=0;
    for(i=center+1;i<=right;i++)
    {
        rights+=a[i];
        if(rights>s2) s2=rights;
    }
    if(s1+s2<left_sum && right_sum<left_sum) return (left_sum);
    if(s1+s2<right_sum) return (right_sum);
    return s1+s2;

}
void display(int a[],int n)
{
    int i;
    for(i=1;i<=n;i++)
    {
        printf("%d  ",a[i]);
    }
    printf("\n");
}

main(){
    /*-2 11 -4 13 -5 -2*/
    int n,a[N],i,sum=0;
    printf("input:");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    printf("output:");
    display(a,n);
    printf("最大子段和为:");
    printf("%d",max_sum(a,n));
}

三、运行结果


 

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值