算法设计与分析第二章作业

题目:

AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[100010],s[100010];
//分治
int solve(int l,int r){
if(l==r){
if(a[l]<0)return 0;
return a[l];
}
int mid=(l+r)/2;
int sl=solve(l,mid),sr=solve(mid+1,r);
//向左
int s1=0,t=0;
for(int i=mid;i>=l;i--){
t+=a[i];
s1=max(t,s1);
}
//向右
int s2=0;t=0;
for(int i=mid+1;i<=r;i++){
t+=a[i];
s2=max(t,s2);
}
int sm=s1+s2;
return max(sm,max(sl,sr));
}
int main(){
int n;
cin>>n;
bool f=1;
for(int i=1;i<=n;i++){
cin>>a[i];
// if(a[i]>=0){
// f=0;
// }
}
cout<<solve(1,n);
// int ma=-1,now=0;
// for(int i=1;i<=n;i++){
// if(now+a[i]>0){
// now+=a[i];
// ma=max(ma,now);
// }else{
// now=0;
// }
// }
// if(f){
// cout<<0;
// }else{
// cout<<ma;
// }
return 0;
}作业:

1. 请以伪代码描述最大子段和的分治算法
//数组的最大子段和有三种可能:
//1.与左半部分的最大子段和相同,为sl
//2.与右半部分的最大子段和相同,为sr
//3.最大子段和跨越了两部分,为sm=s1+s2,s1和s2分别为从中间开始向左右两边计算最大子段和
int solve(int l,int r){
//递归终止条件
if(l==r){
//最小子问题,l==r,此时若该数>0则返回改数,否则返回0
}
//将数组从中间(mid=(l+r)/2)切开,分为a[1:mid]和a[mid+1:n],递归调用solve得到sl和sr,分别代表左边和右边的最大子段和
for(int i=mid;i>=l;i--){
//从中间向左累计s1,得最大值
}
for(int i=mid+1;i<=r;i++){
//从中间向右累计s2,得最大值
}
return //三种情况的最大值
}

2. 分析该算法的时间复杂度
由公式及以下分析:

1.划分:时间复杂度为O(1);

2.求解子问题:每次将问题规模为n的数组划分成2个规模为n/2的子问题,分别对这两个子数组进行递归操作,时间复杂度为2T(n/2);

3.合并:对两个子数组进行合并,时间复杂度为O(n);

得:

T(n) = O(1) n<=1;

​ 2T(n/2) + O(n) n>1;

得该算法的时间复杂度为O(nlogn)。

3. 结合本章的学习,你对分治法的体会和思考
分治法就是 **将大问题分解成小问题,再从小问题入手,分而治之,最后再合并子问题的解 **的一种基本的算法思想0

分治法的三个基本步骤:

1、分解子问题

2、求解子问题(递归调用)

3、合并子问题的解

版权声明:
作者:Zhang, Hongxing
链接:http://zhx.info/archives/142
来源:张鸿兴的学习历程
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录