刷题的日常-股票价格跨度

92 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

刷题的日常-2022年10月21号

一天一题,保持脑子清爽

股票价格跨度

来自leetcode的 901 题,题意如下:

编写一个 StockSpanner 类,它收集某些股票的每日报价,并返回该股票当日价格的跨度。

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

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

理解题意

通过题意,我们可以将信息整理如下:

  • 题目要求我们设计一个类
  • 每次会调用next方法,要求我们返回当前价格比之前价格高的连续的天数
  • 这里有个坑,如果连续是相同的价格,那么往前需要统计相同价格的天数

做题思路

暴力解直接记录所有的值,然后每次调用都往前扫描,直到不大于当前传入的值出现就停止,返回扫描出现的次数 + 1。
这里采用单调栈的方法实现,具体实现就是每次调用需要看下之前的数是否比当前的数小,小的话就需要合并当前值和前面连续天数的统计。其实就是保证栈内的数值一定要是单调递减的,因为如果出现大于当前值的数,后面的也就不会统计到,因此不需要关心之前的数,步骤如下:

  • 开辟一个栈
  • 每次调用next都判断是否小于栈顶的数
    • 小于栈顶的话则返回1,并将当前价格入栈
    • 大于等于栈顶元素的话则循环合并栈顶元素,直到不符合条件
  • 返回合并的结果

代码实现

代码实现如下:

public class StockSpanner {
    int pre;
    LinkedList<int[]> stack;
    public StockSpanner() {
        stack = new LinkedList<>();
    }
    public int next(int price) {
        if (stack.isEmpty() || stack.peek()[0] > price) {
            stack.push(new int[]{price, 1});
            return 1;
        }
        pre = 1;
        while (!stack.isEmpty() && stack.peek()[0] <= price) {
            pre += stack.pop()[1];
        }
        stack.push(new int[]{price, pre});
        return pre;
    }
}

6e2ec33ee2aa8669dbd167e3a32ebc1.jpg