码迷,mamicode.com
首页 > 编程语言 > 详细

连续子数组的和的最大值、最小值以及和的绝对值的最大值、最小值

时间:2015-04-27 10:03:18      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:子数组   最小和   绝对值   最大和   


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

//求子数组的最小和
//利用的是dp的思想,依次遍历数组中的每个元素,把他们相加,如果加起来大于0,则
//把当前元素之和清为0,否则则和最小和比较,更新最小和,最后得到必是子数组的最小和
//时间复杂度:o(n) 空间复杂度:o(1)
int minSum(vector<int> &num)
{
	int min_sum = 0, sum = 0;

	for(int i=0; i<num.size(); i++)
	{
		sum += num[i];
		if(sum > 0) sum = 0;
		if(sum < min_sum)
			min_sum = sum;
	}
	if(min_sum == 0) //数组中只有正数
	{
		min_sum = num[0];
		for(int i=1; i<num.size(); i++)
		{
			if(num[i]<min_sum)
				min_sum = num[i];
		}
	}
	return min_sum;
}

//求子数组的最大和
//利用的是dp的思想,依次遍历数组中的每个元素,把他们相加,如果加起来小于0,则
//把当前元素之和清为0,否则则和最大和比较,更新最大和,最后得到必是子数组的最大和
//时间复杂度:o(n)
int maxSum(vector<int> &num)
{
	int max_sum = 0, sum = 0;

	for(int i=0; i<num.size(); i++)
	{
		sum += num[i];
		if(sum < 0) sum = 0;
		if(sum > max_sum)
			max_sum = sum;
	}
	if(max_sum == 0) //数组中只有负数
	{
		max_sum = num[0];
		for(int i=1; i<num.size(); i++)
		{
			if(num[i]>max_sum)
				max_sum = num[i];
		}
	}
	return max_sum;
}

//求子数组的和的绝对值的最小值
//暴力穷举法
//时间复杂度:o(n^2) 空间复杂度:o(1)
int minAbsSum1(vector<int> &num)
{
	int min_abs_sum = INT_MAX;
	for(int i=0; i<num.size(); i++)
	{
		int cur_sum = 0;
		for(int j=i; j<num.size(); j++)
		{
			cur_sum += num[j];
			if(abs(cur_sum) < min_abs_sum)
				min_abs_sum = abs(cur_sum);
		}
	}
	return min_abs_sum;
}

//求子数组的和的绝对值的最小值
//先计算所有sum[0-j] 0<= j <n,然后对sum[0-j]的数组进行排序,那么对于任何i,j段的和等于:sum[i-j]= sum[0-j] - sum[0-i];
//设置数组sum用来存储子数组0-j的和
//因为已经对sum进行了排序,排序后只需要找到sum[z]-sum[z-1],sum[z]  (0<=z<sum.size())的绝对值的最小值即可。z为排序后的索引
//如果是sum[z]情形,z为排序后的索引,则minAbs = abs(sum[0-i])
//如果是sum[z]-sum[z-1]情形,则minAbs = abs(sum[i]-sum[j])
//时间复杂度:o(nlogn) 空间复杂度:o(n)
int minAbsSum2(vector<int> &num)
{
	if(num.size()==0) return 0;
	if(num.size()==1) return abs(num[0]);
	int min_abs_sum;
	vector<int> sum;
	int cur_sum = 0;
	for(int i=0; i<num.size(); i++)
	{
		cur_sum += num[i];
		if(cur_sum == 0)
			return 0;
		sum.push_back(cur_sum);
	}
	sort(sum.begin(), sum.end());

	min_abs_sum = abs(sum[0]);
	for(int i=0; i<sum.size()-1; i++)
	{
		int temp1 = abs(sum[i+1]);
		int temp2 = abs(sum[i+1]-sum[i]);
		cur_sum = (temp1<temp2)?temp1:temp2;
		if(cur_sum == 0)
			return 0;
		if(cur_sum<min_abs_sum)
			min_abs_sum = cur_sum;
	}
	return min_abs_sum;
}

//求子数组的和的绝对值的最da值
//暴力穷举法
//时间复杂度:o(n^2) 空间复杂度:o(1)
int maxAbsSum1(vector<int> &num)
{
	int max_abs_sum = 0;
	for(int i=0; i<num.size(); i++)
	{
		int cur_sum = 0;
		for(int j=i; j<num.size(); j++)
		{
			cur_sum += num[j];
			if(abs(cur_sum) > max_abs_sum)
				max_abs_sum = abs(cur_sum);
		}
	}
	return max_abs_sum;
}

//求子数组的和的绝对值的最大值
//先计算所有sum[0-j] 0<= j <n,然后对sum[0-j]的数组进行排序,那么对于任何i,j段的和等于:sum[i-j]= sum[0-j] - sum[0-i];
//设置数组sum用来存储子数组0-j的和
//因为已经对sum进行了排序,排序后只需要找到sum[sum.size()-1]-sum[0],sum[z]  (0<=z<sum.size())的绝对值的最大值即可。z为排序后的索引
//如果是sum[z]情形,z为排序后的索引,则maxAbs = abs(sum[0-i])
//如果是sum[sum.size()-1]-sum[0]情形,则maxAbs = abs(sum[i]-sum[j])
//时间复杂度:o(nlogn) 空间复杂度:o(n)
int maxAbsSum2(vector<int> &num)
{
	if(num.size()==0) return 0;
	if(num.size()==1) return abs(num[0]);
	int max_abs_sum;
	vector<int> sum;
	int cur_sum = 0;
	for(int i=0; i<num.size(); i++)
	{
		cur_sum += num[i];
		if(cur_sum == 0)
			return 0;
		sum.push_back(cur_sum);
	}
	sort(sum.begin(), sum.end());
	max_abs_sum = abs(sum[sum.size()-1]-sum[0]);
	for(int i=0; i<sum.size(); i++)
	{
		cur_sum = abs(sum[i]);
		if(cur_sum>max_abs_sum)
			max_abs_sum = cur_sum;
	}
	return max_abs_sum;
}

int main()
{
	int n;
	while(cin>>n)
	{
		vector<int> num;
		int number;
		for(int i=0; i<n; i++)
		{
			cin>>number;
			num.push_back(number);
		}
		cout<<"minSum = "<<minSum(num)<<endl;
		cout<<"maxSum = "<<maxSum(num)<<endl;
		cout<<"minAbsSum1 = "<<minAbsSum1(num)<<endl;
		cout<<"minAbsSum2 = "<<minAbsSum2(num)<<endl;
		cout<<"maxAbsSum1 = "<<maxAbsSum1(num)<<endl;
		cout<<"maxAbsSum2 = "<<maxAbsSum2(num)<<endl;
		cout<<"------------------------------------"<<endl;
	}
	return 0;
}


连续子数组的和的最大值、最小值以及和的绝对值的最大值、最小值

标签:子数组   最小和   绝对值   最大和   

原文地址:http://blog.csdn.net/zuijinhaoma8/article/details/45290145

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!