分治算法和联机算法 最大子段和

今天算法课讲得是分治算法,以最大子段和为 给定由n个整数(可能为负数)组成的序列:a1,a2,…,an,求该序列的最大子段和。

我最开始想到的是联机算法,从头到尾遍历一次,存放当前最大值和总和,总和小于0舍弃。

分治算法是,分成两个段,递归的去解每个段的结果,每个字问题有三种情况,答案在左段,答案在右段,和包括中点,计算三者答案,找max。第三种情况,从中间往两侧走,和比最大之大保留,反之为0.

// 最大子段和问题.cpp : 定义控制台应用程序的入口点。
//
/*
分成两段 作何有
*/
#include "stdafx.h"
#include <iostream>
#include <vector>
using std::vector;
using std::cout;
using std::endl;
//分而治之算法:把序列分成相同等分 最后答案有三种 只在左边的max 右边的max 左右都包含的max
//然后递归去做左序列和右序列
int divide_and_conquer(vector<int> v,int left,int right) //right是要包括的
{
	int sum = 0;
	if (left == right) 
	{
		return v[left] > 0 ? v[left] : 0;
	}
	else 
	{
		int mid = (left + right) / 2;
		int leftsum = divide_and_conquer(v, left, mid);//左边最大值
		int rightsum = divide_and_conquer(v, mid+1, right);
		//包括mid的 从mid往两边走 只要和为正数的 分别设置最大值为s1 s2
		int lefts = 0;//总和
		int s1 = 0;
		for (int i = mid; i >= left; i--) 
		{
			lefts += v[i];
			if (lefts > s1)s1 = lefts;
		}
		int rights = 0;//总和
		int s2 = 0;
		for (int i = mid+1; i <=right; i++)
		{
			rights += v[i];
			if (rights > s2)s2 = rights;
		}
		sum = s1 + s2;
		if (leftsum > sum)sum = leftsum;
		if (rightsum > sum)sum = rightsum;
	}
	return sum;
}
int fun(vector<int> v) //遍历一次 保存当前最大值和目前的和 如果目前的和小于0 舍弃(联机算法)
//联机算法是在任意时刻算法对要操作的数据只读入(扫描)一次,一旦被读入并处理,它就不需要在被
//记忆了。而在此处理过程中算法能对它已经读入的数据立即给出相应子序列问题的正确答案。
{
	int max = 0;
	int sum = 0;
	for (int i = 0; i < v.size(); i++) 
	{
		sum += v[i];
		if (sum < 0)sum = 0;
		if (sum > max)max = sum;
	}
	return max;
}
int main()
{
	vector<int> v = {-2,11,-4,13,-5,-2};
	vector<int> v2 = {-23,18,20,-7,12,-5,-22};
	cout << divide_and_conquer(v2,0,v.size()-1)<< endl;
	cout << fun(v2)<<endl;
	system("pause");
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值