栈的应用-最大宽度坡

且慢 · · 465 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

题目:给定一个数组,每个元素只能取1或-1,求一个最长子数组的长度,满足子数组所有元素求和大于0。

输入:[1,-1,1,-1,-1,1]
输出:3
解释:求和大于0的最长子数组为[1,-1,1],长度为3

思路:

  1. 子数组的和,联想到前缀和,转换为求preSum[j]-preSum[i]>0条件下最大的j-i,这是个典型的最大宽度坡问题
  2. 最大宽度坡的解法:
    2.1 初始化一个栈存元素的索引,要维持单调递减性质;从0索引开始遍历数组,将后面更小的元素的索引依次入栈;这是为了构造坡底,坡底是单调递减的。
    2.2 从末尾开始倒序遍历数组,如果数组值大于栈顶对应的值(大于坡底的值才可能成为坡顶),则计算索引与栈顶的差值,并出栈。索引与栈顶差值的最大值就是最大宽度,最大值应该放在循环判断更新。

是不是觉得很绕?用反证法解释下。
假设[i:j]为最长区间,i不是单调递减栈中的元素;那么一定存在0<=k<i,使array[k]<array[i];那么[k:j]才是最长区间,假设不成立;说明坡底一定存在于单调递减栈中。

代码:

func getLongestWidth(input []int) int {
   preSum := make([]int, len(input)+1)
   for i := 0; i < len(input); i++ {
      preSum[i+1] = preSum[i] + input[i]
   }
   stack := []int{0}
   for i := 1; i < len(preSum); i++ {
      if preSum[i] < preSum[stack[len(stack)-1]] {
         stack = append(stack, i)
      }
   }
   res := 0
   for i := len(input); i > 0; i-- {
      for len(stack) > 0 && preSum[stack[len(stack)-1]] < preSum[i] {
         res = getMax(res, i-stack[len(stack)-1])
         stack = stack[:len(stack)-1]
      }
   }
   return res
}

func getMax(a, b int) int {
   if a > b {
      return a
   }
   return b
}

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:且慢

查看原文:栈的应用-最大宽度坡

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

465 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传