更多算法题的题解见:算法刷题题解汇总(持续更新中)
题解:使用单调栈解决股票价格上涨等待天数问题
一、问题分析
我们需要计算股票价格列表中,从每一天开始至少需要等待多少天才能看到价格上涨。如果没有上涨的情况,则对应位置的值为0。这是一个典型的单调栈问题,我们可以通过维护一个单调递减的栈来找到每个价格之后第一个比它高的价格。
二、解题思路
为了高效解决这个问题,我们可以使用一个单调栈(Monotonic Stack)来辅助计算。
单调栈的概念
单调栈是一种栈的特殊应用,栈中的元素遵循一定的单调性(递增或递减)。在本题中,我们使用的是单调递减栈。栈中的元素表示股票价格的索引,栈顶保存的是当前尚未找到更大价格的最新的日期。通过栈来存储股票价格的索引,并不断更新每个位置的结果。
算法设计
- 初始化一个结果数组
result
,用于存储等待天数。 - 使用一个栈
stack
来存储价格的索引,栈的特性是单调递减,即栈顶元素对应的价格是栈中所有元素对应价格中最小的。 - 从后往前遍历股票价格数组,这样可以保证我们找到的是第一个比当前价格高的价格。
- 栈的操作:对于每个价格,我们比较栈顶元素对应的价格与当前价格:
- 如果栈为空,说明后面没有比当前价格更高的价格,将
result[i]
设置为 0。 - 如果栈不为空,且栈顶的价格小于当前价格,则弹出栈顶元素(因为该价格无法作为上涨的候选),继续判断栈顶元素是否符合条件。
- 如果栈顶的价格大于当前价格,那么栈顶的索引就是下一次上涨的日子,计算当前日期到这个日期之间的天数差,并将该差值作为结果。
- 更新栈:将当前索引入栈,以便后续的价格可以使用它来计算等待天数。
三、代码实现
public class Main {
public static int[] solution(int N, int[] stockPrices) {
int[] result = new int[N];
Stack<Integer> stack = new Stack<>();
for (int i = N - 1; i >= 0; i--) {
// 栈不为空,并且当前价格大于等于栈顶索引对应的价格
while (!stack.isEmpty() && stockPrices[i] >= stockPrices[stack.peek()]) {
stack.pop();
}
// 栈为空或当前价格小于栈顶索引对应的价格
result[i] = stack.isEmpty() ? 0 : stack.peek() - i;
stack.push(i); // 当前索引入栈
}
return result;
}
}
四、复杂度分析
时间复杂度:O(N)
- 该算法中,我们只对股票价格数组进行了一次遍历,从后往前遍历数组中的每个元素。
- 在遍历过程中,每个元素最多只会被压入和弹出栈一次。
因此,整个算法的时间复杂度是线性的,即 O(N),其中 N 是股票价格数组的长度。
空间复杂度:O(N)
- 我们使用了一个栈来存储索引,在最坏的情况下,如果股票价格是单调递增的,那么栈的大小将会是 N。
- 数组
result
的大小也是 N。
因此,空间复杂度是 O(N),这是因为我们需要额外的空间来存储栈和结果数组。