C++ LeetCode 53:最大子序和

这篇博客探讨了如何解决LeetCode中的问题53,寻找给定整数数组的最大子序和。文章介绍了三种解法:暴力求解(O(n^2))、分治法(O(nlog(n))和在线处理(O(n)),并指出在线处理方法最优。示例数组[-2,1,-3,4,-1,2,1,-5,4]的最大子序和为6。" 127298217,11114359,阿里巴巴分布式架构学习手册概览,"['分布式', '架构', '学习', '高可用性', '系统设计']
摘要由CSDN通过智能技术生成

前言
这道题目有三种解法:

  1. 暴力解法:求出所有的子序列和,找到最大的那一个。时间复杂度为O(n^2)
  2. 分治法:将所求序列一分为二,分别求左、右子序列的最大和,然后再求中间跨界的最大和,最后比较三者的大小,找到最大的那一个。时间复杂度为O(nlog(n))
  3. 在线处理:顺序遍历序列求和,将和为负的所有值舍弃,即置零,最后求出和的最大值。时间复杂度为O(n)

题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

实现方法
一、暴力求解

int MaxSubseqSum1(int a[], int n) {
	int CurrentSum, MaxSum = 0;
	for (int i = 0; i < n; i++) {
		CurrentSum = 0;
		for (int j = i; j < n; j++) {
			CurrentSum += a[j];
			if (CurrentSum > MaxSum)
				MaxSum = CurrentSum;
		}
	}
	return MaxSum;
}

二、分治法

//3个数比大小,返回最大值
int MaxNum3(int a, int b, int c) {
	return a > b ? a > c ? a : c : b > c ? b : c;
}

//二分法:递归。 O(nlog(n))
int BinaryMaxSubSum(int list[], int left, int right) {
	int MaxLeftSum, MaxRightSum;
	int MaxBoardSum, MaxLeftBoardSum = 0, MaxRightBoardSum = 0;
	int i, center;

	//判断递归终止条件
	if (left == right) {
		if (list[left] > 0)
			return list[left];
		return 0;
	}

	//进行分治,求得左序列和最大值、右序列和最大值
	center = (left + right) / 2;
	MaxLeftSum = BinaryMaxSubSum(list, left, center);
	MaxRightSum = BinaryMaxSubSum(list, center + 1, right);
	
	//求中间跨界的和最大值
	int LeftBoardSum = 0, RightBoardSum = 0;
	for (i = center; i >= left; i--) {
		LeftBoardSum += list[i];
		if (LeftBoardSum > MaxLeftBoardSum) {
			MaxLeftBoardSum = LeftBoardSum;
		}
	}
	for (i = center + 1; i <= right; i++) {
		RightBoardSum += list[i];
		if (RightBoardSum > MaxRightBoardSum) {
			MaxRightBoardSum = RightBoardSum;
		}
	}
	MaxBoardSum = MaxLeftBoardSum + MaxRightBoardSum;

	//比较三者的大小,返回最大值
	return MaxNum3(MaxBoardSum, MaxLeftSum, MaxRightSum);
}

int MaxSubseqSum2(int a[], int n) {
	return BinaryMaxSubSum(list, 0, n - 1);
}

三、在线处理

int MaxSubseqSum3(int a[], int n) {
	int CurrentSum = 0, MaxSum = a[0];
	for (int i = 0; i < n; i++) {
		CurrentSum += a[i];
		if (CurrentSum > MaxSum) {
			MaxSum = CurrentSum;
		}
		if (CurrentSum < 0) {
			CurrentSum = 0;		//如果子序列和为负,则置零
		}
	}
	return MaxSum;
}

总结
比较上面的三种方法,第三种方法最好。但是分治法的思想也很精妙,需要掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值