LeetCode901. 股票价格跨度 -单调栈(每日一题)

这类题型是单调栈系列,找当前这个数右边的第一个最大的数。可以用一个栈来维护这个数组,然后在找的过程中,不断入栈出栈,实现O(len)的时间复杂度

题目

设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度 。

当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。

例如,如果未来 7 天股票的价格是 [100,80,60,70,60,75,85],那么股票跨度将是 [1,1,1,2,1,4,6] 。

实现 StockSpanner 类:

StockSpanner() 初始化类对象。
int next(int price) 给出今天的股价 price ,返回该股票当日价格的 跨度 。

示例

输入:
[“StockSpanner”, “next”, “next”, “next”, “next”, “next”, “next”, “next”]
[[], [100], [80], [60], [70], [60], [75], [85]]
输出:
[null, 1, 1, 1, 2, 1, 4, 6]

解释:
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // 返回 1
stockSpanner.next(80); // 返回 1
stockSpanner.next(60); // 返回 1
stockSpanner.next(70); // 返回 2
stockSpanner.next(60); // 返回 1
stockSpanner.next(75); // 返回 4 ,因为截至今天的最后 4 个股价 (包括今天的股价 75) 都小于或等于今天的股价。
stockSpanner.next(85); // 返回 6

代码实现

class StockSpanner:

    def __init__(self):
        self.stack = [(-1, inf)]#这里的inf指的是最大值
        self.idx = -1

    def next(self, price: int) -> int:
        self.idx+=1
        while price >=self.stack[-1][1]:#这里的stack也可以理解为二维数组,第一个位置是栈的索引,-1表示栈顶,1表示元素的值
            self.stack.pop()
        self.stack.append((self.idx, price))
        return self.idx - self.stack[-2][0]#这里的-2表示栈顶向下第二个元素的索引,0表示取这个索引的值

这段代码其实也是力扣官方的题解

下面是对代码的实际操作案例

stock = StockSpanner()

# 示例1:[100]
print(stock.next(100))  # 输出: 1

# 示例2:[100, 80]
print(stock.next(80))   # 输出: 1

# 示例3:[100, 80, 60]
print(stock.next(60))   # 输出: 1

# 示例4:[100, 80, 70]
print(stock.next(70))   # 输出: 2

# 示例5:[100, 80, 70, 60]
print(stock.next(60))   # 输出: 1

# 示例6:[100, 80, 75]
print(stock.next(75))   # 输出: 4

# 示例7:[100, 80, 75, 85]
print(stock.next(85))   # 输出: 6

在示例1中,当前价格为100,没有更早的价格可以比较,所以跨度为1。
在示例2中,当前价格为80,前一天的价格为100,因此跨度为1。
在示例3中,当前价格为60,前一天的价格为80,因此跨度为1。
在示例4中,当前价格为70,前一天的价格为80,所以跨度为2。
在示例5中,当前价格为60,前一天的价格为70,跨度重新变为1。
在示例6中,当前价格为75,前一天的价格为60,所以跨度为1+1+1+1=4。
在示例7中,当前价格为85,前一天的价格为75,所以跨度为1+4+1=6。

贴上类似的一题496. 下一个更大元素 I

题目

nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。

给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。

示例

示例 1:

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:

  • 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
  • 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
  • 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

代码

class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        ans = {}
        stack = []
        for num in reversed(nums2):
            while stack and num>stack[-1]:
                stack.pop()
            ans[num] = stack[-1] if stack else -1#这里类似c中的:?三目运算符
            stack.append(num)#这里加入栈需要用append
        return [ans[num] for num in nums1]#这个用法非常巧妙,虽然说可能跟我才开始用python也有关系,不过也算是学到了

对题目的分析,其实这个题使用暴力的办法也可以解决,就是顺着找就行。不过用单调栈的话,能降低相当一部分的时间复杂度,题目的思想类似上面一道,就是将当前最大的元素保留在栈中,然后不断维护栈。过程当中保留了栈的索引或者元素的值,能满足题目要求

你可能感兴趣的:(python,开发语言)