[Golang-Leetcode]最大子序列和-解题思路

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 。
复制代码

暴力解法

看到题目,最容易实现的就是暴力求解,对所有子数组集合完整进行一次遍历计算,时间复杂度为O(n^2):

func maxSubArray(nums []int) int {
   m := nums[0]
   for i := 0; i < len(nums); i++ {
      for j := i; j < len(nums); j++ {
         s := 0
         for t := i; t <= j; t++ {
            s += nums[t]
         }
         if s > m {
            m = s
         }
      }
   }
   return m
}
复制代码

当然,不出意外的超时了:

image.png

贪心算法

通过观察,我们不难发现:当一串子序列向后拓展时,若此时本序列和已经小于0了,那么我们不如直接放弃该子串,直接从下一个元素开始重新构建连续子串。

举个简单的例子,从-2开始构建连续子序列,后面元素为1,那么要想把1加到该子序列中,得到子序列-2, 1序列和为-1。这肯定是不合理的,因为我们直接放弃-2,重新从1开始构建子序列1,序列和为1大于上述子序列。

因此,我们可以通过该特性以子序列和为负数作为分界条件,来求子序列的局部最优解。

同时,每当局部最优解更新更新时,都可以与全局最优进行比对,若大于全局最优解,则更新。

只需一次遍历,就能得到结果,时间复杂度为O(n)。

代码实现如下:

func maxSubArray(nums []int) int {
   m := nums[0]
   tmp := 0
   for i := 0; i < len(nums); i++ {
      tmp += nums[i]
      if tmp > m {
         m = tmp
      }
      if tmp < 0 {
         tmp = 0
      }
   }
   return m
}
复制代码

提交结果

image.png

おすすめ

転載: juejin.im/post/7031934846754619405