求两个子数组最大的累加和

来自牛客网左程云算法第二堂课第一题

问题:给定一个数组,其中当然有很多的子数组,在所有两个子数组的组合中,找到相加和最大的一组,要求两个子数组无重合的部分。最后返回累加和。

要求: 时间复杂度达到 O(N)

解法:我们很容易想到将整个数组分成两个部分,然后分别求这两个部分子数组的最大累加和。将结果累加起来。那么将数组分成不重合两部分(相邻的两部分)有N-1种分法,根据算法原型就是leetcode 53. Maximum Subarray 子数组最大和,求子数组最大和的时间复杂度是O(N),整体的时间复杂度达到了O(N*N)。那么如何将时间复杂度降到O(N)呢?分析我们的算法原型,其中的max会保存遍历到当前位置的子数组的最大和,我们可以将这个值保存起来,这样我们就可以用O(1)的时间复杂度得到当前子数组的最大累加和。整体的时间复杂度也是O(N)级别的。由于我们要将数组分成两部分,预处理时,我们需要计算一遍从右到左的子数组最大和,这样右边的部分我们也可以直接拿到它的子数组最大累加和,左边的部分我们不用数组保存,因为我们是从左到右遍历的,只用一个变量保存即可。这是我们用空间换时间的一个方法。额外空间复杂度为O(N)。

public int maxTwoSubArray(int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}
		int[] h = new int[nums.length];
		h[h.length - 1] = nums[nums.length - 1];
		int cur = h[h.length - 1];
		for (int i = h.length - 2; i >= 0; i--) {
			cur += nums[i];
			h[i] = Math.max(cur, h[i + 1]);
			if (cur < 0) {
				cur = 0;
			}
		}
		int max = Integer.MIN_VALUE;
		int lMax = Integer.MIN_VALUE;
		cur = 0;
		for (int i = 0; i < nums.length - 1; i++) {
			cur += nums[i];
			lMax = Math.max(lMax, cur);
			max = Math.max(max, lMax + h[i + 1]);
			if (cur < 0) {
				cur = 0;
			}
			System.out.println(lMax + " " + h[i+1] + " " + i + " " + max);
		}
		return max;
	}


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线段树和树状数组都是用于解决区间查询问题的数据结构,它们在不同的场景下有不同的应用。 首先,树状数组(Binary Indexed Tree,BIT),也称为Fenwick树,是一种用于高效实现区间查询的数据结构。它通过将原始数组进行分块存储,在每个块内用累加的方式存储前缀和,从而实现了快速的区间查询和单点更新操作。树状数组的主要优势是实现简单、效率高,适用于解一维区间和问题,例如动态数组前缀和、解逆序对等。但是树状数组不适用于区间修改操作,即不能有效地处理某个区间内的元素更新。 其次,线段树(Segment Tree)是一种二叉树的数据结构,用于处理区间查询和更新操作。线段树将整个区间划分为若干个区间,并在每个节点中存储该区间的某种统计信息,例如区间和、最大值、最小值等。线段树的构造过程是一个递归的过程,通过不断地划分区间直到达到单个元素的程度。线段树的主要优势是能够高效地处理区间查询和区间修改操作,适用于解决多维区间查询问题,例如区间最值查询、区间更新等。 总之,树状数组和线段树都是用于解决区间查询问题的数据结构。树状数组适用于一维场景,实现简单、效率高,但不能处理区间修改操作;线段树适用于多维场景,能够高效地处理区间查询和修改操作。在实际问题中,根据具体情况选择适合的数据结构可以提高解题效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值