课程笔记分治策略

分治策略

分治策略是对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同。
递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
其实分治策略是一种不同的递归,递归算法是整体递归,分治策略是分开递归。

基本步骤

分治法在每一层递归上都有三个步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
合并:将各个子问题的解合并为原问题的解。

适用条件

分治法所能解决的问题一般具有以下几个特征:
1、该问题的规模缩小到一定的程度就可以容易地解决;
2、该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
3、利用该问题分解出的子问题的解可以合并为该问题的解;
4、该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

求最大子段和问题

求最大子段和有动态规划和分治等多种方法,最近看一些大厂的面试题里边就有这个算法设计。最近看的是携程的笔试就是求最大子段和问题,所以最好是这个问题多种解决策略都能够熟悉和掌握。这道题先用分治的思想去做。
问题描述:
给定由n个整数组成的序列(a1, a2, …, an),最大子段和问题要求该序列形如
的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。例如,序列(-20, 11, -4, 13, -5, -2)的
最大子段和为:在这里插入图片描述

代码实现

#include<iostream>
using namespace std;
int MaxSum(int a[], int left, int right)
{
	int sum = 0;
	if (left == right)
	{
		if (a[left] > 0)
		{
			sum = a[left];
		}
		else
		{
			sum = 0;
		}
	}
	else
	{
		int center = (left + right) / 2;
		int leftSum = MaxSum(a, left, center);
		int rightSum = MaxSum(a, center + 1, right);
		int s1 = 0, lefts = 0;
		for (int i = center; i >= left; --i)
		{
			lefts += a[i];
			if (lefts > s1)
				s1 = lefts;
		}
		int s2 = 0, rights = 0;
		for (int i = center + 1; i <= right; ++i)
		{
			rights += a[i];
			if (rights > s2)
				s2 = rights;
		}
		sum = s1 + s2;
		if (sum < leftSum)
			sum = leftSum;
		if (sum < rightSum)
			sum = rightSum;
	}
	return sum;
}
int main()
{
	int n, a[1050];
	cin >> n;
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i];
	}
	cout << MaxSum(a, 0, n - 1);
	return 0;
}
/*
6
-20 11 -4 13 -5 -2

结果:
20
*/
发布了134 篇原创文章 · 获赞 18 · 访问量 8384
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览