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

#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;
}
时间: 2024-10-29 10:15:58

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

【原题】求两个不相交的连续子数组的最大和

题目: 有一个整数数组n,a和b是n里两个互不相交的子数组.返回sum(a)+sum(b)的最大值. 分析: 新建两个数组left和right,left[i]表示n[0:i]的连续子数组的最大和,right[i]表示n[i:length-1]的连续子数组的最大和.left[i]+right[i+1]的最大值就是答案. int SumOfTwoSubarray(const vector<int> &n) { if (n.size() < 2) { throw exception()

返回一个数组的连续子数组和的最大值

package wodeshiyao; import java.util.Scanner; public class lalala { static Scanner scan=new Scanner(System.in); public static void main(String[] args) { // TODO Auto-generated method stub int b; System.out.println("请输入数组长度:"); b=scan.nextInt();

求环形连续子数组的和的最大值

课上老师把连续子数组求和的题目改为让子数组首尾相接再求最大子数组的和. 我的处理方法:新建一个二倍原数组长度b的数组d[  ],然后从d[0]到d[b]分别生成b个分数组,再分别求子数组和,再比较. package wodeshiyao; import java.util.Scanner; public class shiyan321 { static Scanner scan=new Scanner(System.in); public static void main(String[] ar

Task 4 求数组的连续子数组的最大和(团队合作)

小组成员:李敏.刘子晗 1.设计思想:由于已经做过这个题目,只要对之前的程序加上相应的测试和约束即可.我们两个人一起商议后,决定了程序的主框架和并列出了最终可以实现的功能.先要定义数组长度和上下限的变量,然后通过if语句对用户所给出的长度和数值进行判断看是否合法,如果不合法要重新输入.最后再加上之前求和的相应代码即可. 2.出现的问题:我们达成协议后,李敏负责编程,我负责测试.开始写程序,在写判断数值是否满足int整型范围的时候出现了错误,我在测试的时候发现她把小于号错写成了大于号,然后加以改正

关于求已知整数数组的连续子数组的最大和的方法

日期:2019.3.9 博客期:039 星期六 这次的标题就是题目——关于求已知整数数组的连续子数组的最大和的方法,打个比方:给予数组 { 1 , -2 , 3 , -1 , 0 , 2 } ,它的连续子数组的最大和就是取得 { 3 , -1 , 0 , 2 } 时的和 4 !就是说我们需要找到元素值和最大的子数组.我们大可以考虑几种方法: (1)先求出所有的子数组,再找出每一组的和,求出和的最大值 >>>>>>>(优化)>>>>>&

求连续子数组的最大和

一.题目: 这是一道考的烂的不能再烂的题目,但是依然有很多公司乐于将这样的题目作为笔试或面试题,足见其经典. 问题是这样的:一个整数数组中的元素有正有负,在该数组中找出一个连续子数组,要求该连续子数组中各元素的和最大,这个连续子数组便被称作最大连续子数组.比如数组{2,4,-7,5,2,-1,2,-4,3}的最大连续子数组为{5,2,-1,2},最大连续子数组的和为5+2-1+2=8. 二.解法: 解法一:暴力求解法 /* (1) 常规方法,时间复杂度O(n*n) (2) 先从第一个元素开始向后

[算法导论]4.1-5最大连续子数组问题

在线性时间内非递归的求数组的最大连续子数组(连续和最大的子数组). 题目给出思路为数组A[1...j+1]的最大和子数组,有两种情况:a) A[1...j]的最大和子数组; b) 某个A[i...j+1]的最大和子数组,但思考很久没有理解如何用这个思路设计线性时间算法,希望有人能给予指点. (i点是使A[1]+..+A[i]为负的一个值?) 目前的思路是,最大子数组一定位于从某个正数开始,全部求和<=0的一段数组中 从其实点i到目标点j,从第一个正数开始截取尽量长的一段数组,从第一个正数起的最大

lintcode循环数组之连续子数组求和

v 题目:连续子数组求和 II 给定一个整数循环数组(头尾相接),请找出一个连续的子数组,使得该子数组的和最大.输出答案时,请分别返回第一个数字和最后一个数字的值.如果多个答案,请返回其中任意一个. v 样例 给定 [3, 1, -100, -3, 4], 返回 [4,0]. v 思路 1.如果不是循环数组,求解连续子区间和的思路如下: 首先设一个累加变量和sum和最大值变量maxN,[ld, rd]表示当前正在累加的区间,[lt,rt]表示最大和的区间.从左边开始一直累加,并初始当前区间[ld

【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大

Add Date 2014-09-23 Maximum Product Subarray Find the contiguous subarray within an array (containing at least one number) which has the largest product. For example, given the array [2,3,-2,4],the contiguous subarray [2,3] has the largest product = 

编程算法 - 连续子数组的最大和 代码(C)

连续子数组的最大和 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一个整型数组, 数组里有正数也有负数. 数组中一个或连续的多个整数组成一个子数组.求所有子数组的和的最大值. 使用一个数保存当前和, 如果当前和为小于0,  则替换新值, 否则, 递加, 使用一个数保存临时最大值. 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <stdio