分治法思想求最大子段和

计科2201李佳喆 2022级 2023-10-09 20:20:07

int maxmerge(int a[], int left, int right)

{

int mid = (left+right)/2;

int s1,s2,sum=0,max=-10000;

if(left == right) return a[left];

s1 = maxmerge(a,left,mid);

s2 = maxmerge(a,mid+1,right); //分解子问题

for(int i=mid;i>=0;i--)

{

sum += a[i];

if(sum > max) max = sum;

}

sum = max; //求解子问题

for(int i=mid+1;i<=right;i++)

{

sum += a[i];

if(sum > max) max = sum; //合并子问题

}

if(max<s1) max = s1;

else if(max<s2) max = s2;

return max;

}
最大值有以下三种情况:
整个序列的字段和与左半部分相同
整个序列的子段和与右半部分相同
整个序列的子段和 在两个部分的中间连接部分

分解子问题:O(1)
求解子问题:拆分子数组分别求得两个长度为n/2的最大子段和,时间复杂度2T(n/2)
合并子问题:O(n)
T(n)=2T(n/2)+O(n)=O(nlogn)

分治法将一个问题划分为数个可以用相同方式求解的子问题,使得子问题的规模简单到可以直接求解,而原问题就是这些子问题的解的合并。

...全文
125 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-10-09
精选
  • 打赏
  • 举报
回复
您的问题已经帮您同步至问答, 链接: https://ask.csdn.net/questions/8008960, 请您保持关注, 如果回答有帮助解决此问题, 麻烦您动动小手给相关的回答点赞, Ada会在评论区为您更新结题状态
老牛毕设 2023-10-09
  • 打赏
  • 举报
回复

这段代码是一个使用分治策略的函数,旨在找出给定数组中的最大子段和。不过,我有几个点想要提出:

你的注释中,你提到“整个序列的字段和与左半部分相同”,我想这可能是指“整个序列的子段和与左半部分相同”。如果这是你的意图,你可能希望在代码中明确这一点。
你在代码中两次遍历了数组的部分元素来找出最大的子段和。这部分代码可能存在问题。在第一次遍历中,你计算了从mid到0的和,并在和大于max时更新max。然后在第二次遍历中,你再次计算了和,并在和大于max时再次更新max。但是,你应该只在第二次遍历中更新max,因为第二次遍历包括了在第一次遍历中被忽略的元素。
在函数maxmerge的最后一行,你返回的是max而不是maxmerge(a, left, mid)或maxmerge(a, mid+1, right)。这可能是一个错误,因为你可能需要从子数组的最大和中选择最大的一个。
以下是我对你的代码进行的一些修改:

int maxmerge(int a[], int left, int right) {
    if(left == right) return a[left]; // if there's only one element, return it
    
    int mid = (left + right) / 2;
    int s1 = maxmerge(a, left, mid); // merge the left half
    int s2 = maxmerge(a, mid + 1, right); // merge the right half
    
    // merge the two subarrays and find the maximum sum
    int sum = 0, max = -10000;
    for(int i = mid; i >= 0; i--) { // merge from mid to the start of the array
        sum += a[i];
        if(sum > max) max = sum;
    }
    for(int i = mid + 1; i <= right; i++) { // merge from mid+1 to the end of the array
        sum += a[i];
        if(sum > max) max = sum;
    }
    
    return max != -10000 ? max : (s1 > s2 ? s1 : s2); // if max is still the initial value, it means there's no sum greater than -10000, so return the greater between s1 and s2
}

在这个修改后的版本中,我首先合并左半部分和右半部分的子数组,然后合并两个子数组并找出最大的和。最后,如果最大和不在两个子数组中,我就返回两个子数组中的最大值;否则,我返回最大的和。

434

社区成员

发帖
与我相关
我的任务
社区描述
广东外语外贸大学信息科学与技术学院
算法 高校
社区管理员
  • brisksea
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧