描述

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

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

数据范围:

  • 1<=n<=10^5
  • -100 <= a[i] <= 100

要求:时间复杂度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]

// 输入:
[1,2,-3,4,-1,1,-3,2]
// 返回值:
[1,2,-3,4,-1,1]
// 说明:经分析可知,最大子数组的和为4,有[4],[4,-1,1],[1,2,-3,4],[1,2,-3,4,-1,1],故返回其中长度最长的[1,2,-3,4,-1,1]

// 输入:
[-2,-1]
// 返回值:
[-1]
// 说明:子数组最小长度为1,故返回[-1] 
解题思路

动态规划+滑动区间

代码实现
package main

import "fmt"

/**
 * [JZ42-简单] 连续子数组的最大和
 *
 * @param array int 一维数组
 * @return int
 */
func findGreatestSumOfSubArr(array []int) []int {
    length := len(array)
    if 1 == length {
        return array
    }

    dp := make([]int, length)
    dp[0] = array[0]
    max := array[0]

    // 滑动左右区间值 left、right 和最长区间值 l、r
    left, right, maxLeft, maxRight := 0, 0, 0, 0
    for i := 1; i < length; i++ {
        right++

        // 前面连续数字和小于当前数,则重新开始
        if dp[i-1]+array[i] < array[i] {
            dp[i] = array[i]
            left = right
        } else {
            dp[i] = dp[i-1] + array[i]
        }

        if dp[i] > max || dp[i] == max && (right-left) > (maxRight-maxLeft) {
            max = dp[i]
            maxLeft = left
            maxRight = right
        }
    }

    return array[maxLeft : maxRight+1]
}

func main() {
    arr := []int{1, -2, 3, 10, -4, 7, 2, -5}
    ret := findGreatestSumOfSubArr(arr)
    fmt.Println(ret)
}

本文由 一切随风 创作,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论