Skip to content

Latest commit

 

History

History
67 lines (54 loc) · 1.99 KB

85.md

File metadata and controls

67 lines (54 loc) · 1.99 KB

连续子数组的最大和(二)

题目

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组

  1. 子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
  2. 如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个
  3. 该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组
  4. 返回的数组不计入空间复杂度计算

要求:时间复杂度O(n),空间复杂度O(n) 进阶:时间复杂度O(n),空间复杂度O(1)

示例

输入:[1,-2,3,10,-4,7,2,-5]

返回值:[3,10,-4,7,2]

说明:经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18,故返回[3,10,-4,7,2]

思路

  • dp数组表示以下标i为终点的最大连续子数组和
  • 连续的子数组要么加上变得更大,要么它本身就更大
  • 状态转移为 dp[i] = max(dp[i−1] + array[i], array[i])
  • 同时记录子数组的起始下标,每次更新最大值的时候,顺便更新最终的区间首尾
  • 最后根据区间首尾获取子数组

实现

func FindGreatestSumOfSubArray(array []int) []int {
	res := make([]int, 0)
	dp := make([]int, len(array))
	dp[0] = array[0]
	var maxSum = dp[0]
	var left, right int
	var leftRes, rightRes int
	for i := 1; i < len(array); i++ {
		right++
		dp[i] = max(dp[i-1]+array[i], array[i])
		if dp[i-1]+array[i] < array[i] {
			// 当前值比和前边最大加起来都大了,那这就是新边界
			left = right
		}
		if dp[i] > maxSum || dp[i] == maxSum && (right-left+1) > (rightRes-leftRes+1) {
			// 和更大或者和一样数组更长
			maxSum = dp[i]
			leftRes = left
			rightRes = right
		}
	}
	for i := leftRes; i <= rightRes; i++ {
		res = append(res, array[i])
	}
	return res
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}