【LeetCode每日一题】【单调栈】2022-10-21 901. 股票价格跨度 Java实现


题目链接

https://leetcode.cn/problems/online-stock-span/

题目

在这里插入图片描述

我的思路

方案一 LinkedList,从后往前遍历,超时

用LinkedList存储每一次添加进来的price,然后从后往前遍历,找出连续小于等当前位置数的个数,不过,超时

import java.util.LinkedList;
import java.util.List;

class StockSpanner {

    private List<Integer> list;

    public StockSpanner() {
        list = new LinkedList<>();
    }

    public int next(int price) {
        list.add(price);
        int cnt = 0;
        int i = list.size() - 1;
        while (price >= list.get(i)){
            cnt++;
            i--;
        }
        return cnt;
    }
}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */

方案二 两个Stack,超时

import java.util.Stack;

public class StockSpanner {

    private Stack<Integer> s1, s2;

    public StockSpanner() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }

    public int next(int price) {

        int cnt = 1;
        while (!s1.isEmpty() && price >= s1.peek()) {
            s2.add(s1.pop());
            cnt++;
        }
        while (!s2.isEmpty()) {
            s1.add(s2.pop());
        }
        s1.add(price);
        return cnt;
    }
}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */

官方思路 单调栈 计算差值

调用next时,输入的是新的一天的股票价格,需要返回包含在此日内的,往前数最多有连续多少日的股票价格是小于等于今日的股票价格的。

如果把每日的price当成数组不同下标的值,即需要求出每个值与上一个更大元素之间的下标之差。

这种题目可以用单调栈来求解。

此题在具体解法上,栈的元素可以是股票价格的下标(即天数)和股票价格的二元数对,并且在栈中插入一个最大值作为天数为-1天的价格,来保证栈不会为空。

调用next时,先将栈中价格小于等于此时price的元素都弹出,直到遇到一个大于price的值,并将price入栈,计算下标返回差
在这里插入图片描述

import java.util.Stack;

public class StockSpanner {

    private Stack<int[]> s1;
    private int idx;

    public StockSpanner() {
        s1 = new Stack<>();
        s1.add(new int[]{-1, Integer.MAX_VALUE});
        idx = -1;
    }

    public int next(int price) {
        while (price >= s1.peek()[1]) {
            s1.pop();
        }
        idx++;
        int res = idx - s1.peek()[0];
        s1.add(new int[]{idx, price});
        return res;
    }
}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */

其他解法

方案一 利用堆栈实现

https://leetcode.cn/problems/online-stock-span/solution/-by-muse-77-byhj/

首先,根据题目描述,可以发现只有股票趋势是下降的情况下,才会统计跨度日期。

这里的股票趋势下降,应该是从后往前看,是下降趋势时,才进行统计。

可以利用堆栈来进行跨度日期的计算。堆栈操作有如下三种情况:

  • 如果堆栈为空,则直接入栈
  • 如果栈顶元素price 大于 输入股票的price,则直接入栈
  • 如果栈顶元素的price 小于 输入股票的price,则将栈顶元素出栈,并将栈顶元素的day值加到“输入股票”的day值上。然后再对比下一个栈顶元素,操作以此类推,直到发现当前的栈顶元素大于输入股票的price,则将输入股票入栈即可
    在这里插入图片描述

在这里插入图片描述

import java.util.Stack;

public class StockSpanner {

    private Stack<Stock> stack;

    public StockSpanner() {
        stack = new Stack<>();
    }

    public int next(int price) {
        int day = 1;
        while (!stack.isEmpty() && stack.peek().price <= price) {
            day += stack.pop().day;
        }
        stack.add(new Stock(price, day));
        return day;
    }

    class Stock {
        int price;
        int day;

        public Stock(int price, int day) {
            this.price = price;
            this.day = day;
        }
    }
}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */

方案二 利用数组+指针实现

第二种方式,采用两个数组,分别是prices用来记录股票价格和days用来记录跨度天数。那么针对第n次输入的股票,它的价格和跨度天数就是prices[n]和days[n]

除了prices和days这两个数组之外,我们还需要两个指针,分别是:

  • index指针,用来指向“待输入股票”
  • p指针,index指针的前一个指针,用来与“待输入股票”的price进行对比用的,如果它的price小于等于“待输入股票”的price,p就会向前移动

关于p向前移动的格子的数量,就是days的具体值;当days等于1时,就向前移动1个格子;如果days等于2时,就向前移动2个格子(因为days等于2,说明已经是两个格子聚合果的值了,就不需要重复统计了)。
在这里插入图片描述

public class StockSpanner {

    int index = 0;
    int[] prices, days;

    public StockSpanner() {
        prices = new int[10005];
        days = new int[10005];
        index = 0;
    }

    public int next(int price) {
        int p = index - 1;
        while (p >= 0 && prices[p] <= price) {
            p -= days[p];
        }
        prices[index] = price;
        days[index] = index - p;
        return days[index++];
    }

}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值