单调栈解决数组左右两边第一个比当前值大的数

题目描述

给你一个数组,请你求出每一个位置上左边以及右边距离最近的比它大的数。要求时间复杂度O(N)

思路分析

一般思路就是每个位置,左右遍历找,但是这样的时间复杂度是O(N^2),因此,如何实现时间复杂度O(N)?那就是要用到单调栈问题。

单调栈

维护一个栈,要求栈从上到下是从小到大的顺序。
流程:
把数组元素从前开始依次入栈,然后,每次入栈前,和栈顶元素比较,如果比栈顶元素小,就直接入栈,如果大于栈顶元素,就把栈顶元素出栈,同时,每出栈一个数,这个数其实就找到了结果,它栈下面的数,其实就是左边第一个比它大的数,让它出栈的那个数,就是右边第一个比它大的数。
为什么会这样?
首先来解释当前出栈的数,下面的数为什么是左边第一个比它大的数?左边第一个,其实就是上一个入栈的,对吧?如果他俩之间还有数,这个数,如果比下面的还大,那下面的应该弹出了,对吧?所以不可能。如果他俩之间的数比后面的大?那么,他俩就不应该挨着,对吧?因此,栈下面的数就是左边第一个比它大的数。
那么,为什么让他出栈的数是右边第一个比它大的数呢?
因为,如果不比她大,那么应该继续入栈才对,不需要出栈,对吧?如果比他大,那么,如果不是右边第一个,当前数应该早就弹出了,对吧?因此,让他出栈的数是右边第一个比它大的数。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 最长单调递增子序列问题是指在一个序列中找到一个最长的子序列,使得这个子序列中的元素是单调递增的。对于由n个数组成的序列,可以使用动态规划算法来解决最长单调递增子序列问题。具体步骤如下: 1. 定义状态:设dp[i]表示以第i个元素结尾的最长单调递增子序列的长度。 2. 初始化状态:dp[i]的初始为1,因为以第i个元素结尾的最长单调递增子序列至少包含它本身。 3. 状态转移方程:对于第i个元素,遍历前面的元素j(j<i),如果a[j]<a[i],则dp[i]=max(dp[i],dp[j]+1),即以第i个元素结尾的最长单调递增子序列长度为前面所有小于它的元素中最长的子序列长度加1。 4. 最终结果:遍历dp数组,找到最大即为最长单调递增子序列的长度。 例如,对于序列{5,3,4,8,6,7},其最长单调递增子序列为{3,4,6,7},长度为4。 ### 回答2: 动态规划算法是解决最长单调递增子序列的一种有效方法。给定一个由n个数字组成的序列P[1],P[2],……,P[n],我们可以将其拆分成许多长度小于等于n的子序列。这些子序列中的最长单调递增子序列即为原序列的最长单调递增子序列(注意这里的子序列不要求连续)。 我们设D[i]为以P[i]为结尾的最长单调递增子序列的长度,则对于所有的j(1<=j<i),如果P[j]<P[i],那么有: D[i] = max(D[i], D[j]+1) 初始时,D[i]均初始化为1,表示以每个元素为结尾的最长单调递增子序列长度默认为1。从D[1]到D[n]依次计算即可得到整个序列的最长单调递增子序列长度。 接下来,我们以一个长度为10的序列为例进行演示: 设P[1]=5, P[2]=1, P[3]=4, P[4]=2, P[5]=3, P[6]=9, P[7]=7, P[8]=6, P[9]=8, P[10]=10。 首先,初始化D数组,将其所有元素设为1: D[1]=1, D[2]=1, D[3]=1, D[4]=1, D[5]=1, D[6]=1, D[7]=1, D[8]=1, D[9]=1, D[10]=1。 从i=2开始,依次计算D[2]到D[10]: D[2] = max(D[2], D[1]+1) = 2 D[3] = max(D[3], max(D[1], D[2])+1) = 2 D[4] = max(D[4], max(D[1], D[2], D[3])+1) = 2 D[5] = max(D[5], max(D[1], D[2], D[3], D[4])+1) = 3 D[6] = max(D[6], max(D[1], D[2], D[3], D[4], D[5])+1) = 4 D[7] = max(D[7], max(D[1], D[2], D[3], D[4], D[5])+1) = 4 D[8] = max(D[8], max(D[1], D[2], D[3], D[4], D[5], D[7])+1) = 4 D[9] = max(D[9], max(D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8])+1) = 5 D[10] = max(D[10], max(D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8], D[9])+1) = 6 最终D数组为 D=[1, 2, 2, 2, 3, 4, 4, 4, 5, 6],它的最大即为原序列的最长单调递增子序列长度为6,它可以对应的子序列为[1, 4, 5, 6, 8, 10]。 ### 回答3: 最长单调递增子序列问题(Longest Increasing Subsequence,简称LIS)是一个经典的计算机科学问题,它的解法有很多种。其中比较常见的是动态规划算法和贪心算法。 动态规划算法的思路是构建一个数组dp来存储以每个数字结尾的最长单调递增子序列的长度。具体来说,假设我们已经求出了前i-1个数字结尾的最长单调递增子序列的长度dp[1]、dp[2]、……dp[i-1],那么我们可以考虑把第i个数字加入进去,看看是否能够延长截止到i的最长单调递增子序列。因此我们需要从前面的数字中找出所有小于第i个数字的数字,计算出以这些数字结尾的最长单调递增子序列的长度,然后把这些长度加1,取其中的最大即可。具体的表达式可以写为: dp[i] = max{dp[j] + 1 | j < i && a[j] < a[i]} 其中a表示原始序列,dp数组的初始都为1,表示每个数字本身构成一个长度为1的单调递增子序列。最终的结果即为dp数组中的最大。 贪心算法的思路则是利用二分查找来维护一个目前为止最长的单调递增子序列。具体来说,我们从左到右遍历原始序列,然后维护一个数组d,记录目前为止已经找到的最长单调递增子序列。假设我们已经找到了前i-1个数字的最长单调递增子序列d[1]、d[2]、……d[k],并且d[k]是目前为止的最大,那么我们可以把第i个数字插入进去。如果a[i]大于d[k],则可以直接把a[i]加到数组后面,因为它可以延长已有的最长单调递增子序列。否则,我们可以使用二分查找找到满足d[j] < a[i]的最大位置j,然后把a[i]插入到d[j+1]的位置上。因为d[j+1]是目前为止长度为j+1的单调递增子序列的末尾,所以插入a[i]以后,仍然是长度为j+2的单调递增子序列的末尾。 根据以上两种算法,我们可以解决由n个数组成的序列的最长单调递增子序列问题。不同的算法具有不同的时间和空间复杂度,选择合适的算法可以在保证正确性的前提下,提高计算效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值