最大子序列分治实现以及改进

本文介绍了一种使用分治法解决最大子序列问题的方法,并通过两种不同的数据结构实现了该算法。一种是使用向量来存储中间结果,另一种是定义了一个结构体来存储左边界、右边界及序列和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最大子序列,一开始我是用比较方便的向量的:
#include <string>
#include <iostream>
#include <vector>
#include<climits>
using namespace std;


vector<int> f_m_c_s(vector<int> &a,int low,int mid,int high){
	int left_sum=INT_MIN;
	int sum=0;
	int max_left;
	for(int i=mid-1;i!=low-1;--i){
		sum=sum+a[i];
		if(sum>left_sum){
			left_sum=sum;
			max_left=i;}}
	int right_sum=INT_MIN;
	sum=0;
	int max_right;
	for(int j=mid;j!=high;++j){
		
		sum=sum+a[j];
		if(sum>right_sum){
			right_sum=sum;
			max_right=j;}}			
	
	return vector<int>{max_left,max_right,left_sum+right_sum};}
	
vector<int> f_m_s(vector<int> a,int low,int high){
	if(high==low+1){return vector<int>{low,high,a[low]};}
	else{int mid=(low+high)/2;
		 vector<int>a1 = f_m_s(a,low,mid);
		 int left_low=a1[0],left_high=a1[1],left_sum=a1[2];
		 //cout<<"low=";
		 //for(auto i:a1){cout<<i<<" ";}
		 //cout<<'\n'<<endl;
		 
		 vector<int>a2=f_m_s(a,mid,high);
		 int right_low=a2[0],right_high=a2[1],right_sum=a2[2];
		 //cout<<"high=";
		 //for(auto i:a2){cout<<i<<" ";}
		 //cout<<'\n'<<endl;
		 
		 vector<int>a3=f_m_c_s(a,low,mid,high);
		 int cross_low=a3[0],cross_high=a3[1];
		 int cross_sum=a3[2];
		 //cout<<"cross=";
		 //for(auto i:a3){cout<<i<<" ";}
		 //cout<<'\n'<<endl;
		 
		 if(left_sum>=right_sum && left_sum>=cross_sum){
		 	return a1;}
		 else if(right_sum>=left_sum && right_sum>=cross_sum){
		 	return a2;}
		 else {return a3;}}}

但是格式十分麻烦,看了网上的答案之后,发现可以定义一个类,专门用来储存三个数字。

实现:

typedef struct{
	unsigned left; unsigned right; unsigned sum;} ma;

这样把上面的分治方法再写一次:

ma f_m_c_s_ma(int a[], unsigned low, unsigned mid, unsigned high){
	ma result;
	int left_sum=INT_MIN;
	int sum=0;
	for(int i=mid-1;i!=low-1;--i){
		sum=sum+a[i];
		if(sum>left_sum){
			left_sum=sum;
			result.left=i;}}
	int right_sum=INT_MIN;
	sum=0;
	for(int j=mid;j!=high;++j){
		sum=sum+a[j];
		if(sum>right_sum){
			right_sum=sum;
			result.right=j;}}
	result.sum=left_sum+right_sum;
	return result;}
	
ma f_m_s_ma(int a[],unsigned low,unsigned high){
	if(high==low+1){
		ma result={low,high,a[low]};
		return result;}
	else{
		int mid=(low+high)/2;
		ma left=f_m_s_ma(a,low,mid);
		ma right=f_m_s_ma(a,mid,high);
		ma cross=f_m_c_s_ma(a,low,mid,high);
		
		if(left.sum>=right.sum && left.sum>=cross.sum){
			return left;}
		else if(right.sum>=left.sum && right.sum>=cross.sum){
			return right;}
		else {return cross;}}}

理论上是没有错的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值