• 【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);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    方案二 两个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);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    官方思路 单调栈 计算差值

    调用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);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    其他解法

    方案一 利用堆栈实现

    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);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

    第二种方式,采用两个数组,分别是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);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    2022win7cf烟雾头最新调法
    排序算法:非比较排序(计数排序)
    精品基于NET实现的论坛管理系统
    通过后台系统添加一段div,在div中写一个<style></style>标签来修改div外面的元素的深层元素的样式
    QScrollArea设置透明和去除边框
    利用rpmbuild 打包可执行文件和链接库生成rpm 包
    git rebase
    【PL理论】(3) F# 数据类型:变量类型 | F# 操作符 | 定义函数 | 使用定义的函数 | if-then-else 表达式:绝对不能省略 else 部分,除非表达式是 unit 类型
    加密算法 — — 对token进行非对称加密【RSA】
    Java类的继承
  • 原文地址:https://blog.csdn.net/guliguliguliguli/article/details/127438824