持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
1. 题目与解析
编写一个
StockSpanner类,它收集某些股票的每日报价,并返回该股票当日价格的跨度。今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。
例如,如果未来7天股票的价格是
[100, 80, 60, 70, 60, 75, 85],那么股票跨度将是[1, 1, 1, 2, 1, 4, 6]。
输入: ["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]]
输出: [null,1,1,1,2,1,4,6]
解释:
- 首先,初始化 S = StockSpanner(),然后:
- S.next(100) 被调用并返回 1,
- S.next(80) 被调用并返回 1,
- S.next(60) 被调用并返回 1,
- S.next(70) 被调用并返回 2,
- S.next(60) 被调用并返回 1,
- S.next(75) 被调用并返回 4,
- S.next(85) 被调用并返回 6。
注意 (例如) S.next(75) 返回 4,因为截至今天的最后 4 个价格 (包括今天的价格 75) 小于或等于今天的价格。
根据题目,我们需要贮存所有已经插入的数值,最直白的思路就是在第i位直接反过来遍历前i-1位,但是这样会存在重复遍历的问题,因此我们需要考虑通过记忆化的方式尽量减少重复的遍历操作。
我们知道,在插入每一位i的同时,我们会输出紧挨着他的,比他小或者相等的数值的数量,我们存下每一个需要输出的数值,在插入i+1时,就可能存在两种情况:
i+1的数值 >=i的数值,在这种情况下,直接输出1;i+1的数值 <i的数值,在这种情况下,比i小的数值都不需要比较了,可以跳过这些再去比较i-1-n的数值,n是i前方小于等于其本身的数字的个数。
2. 题解
class StockSpanner {
List<Integer> num = new ArrayList<>();
List<Integer> count = new ArrayList<>();
public StockSpanner() {
num.add(Integer.MAX_VALUE);
count.add(-1);
}
public int next(int price) {
num.add(price);
int prev = num.size() - 2;
while (num.get(prev) <= price) {
prev = count.get(prev);
}
count.add(prev);
return num.size() - 1 - prev;
}
}