开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情
[901. 股票价格跨度]
题目的本质就是:求当前位置的元素与「 上一个更大元素」之间相隔的元素个数, 换种说法就是:假设当前位置的值是price,求左边大于price的第一个数的位置和当前位置的差距
做法1:类的成员是一个vector,用于存放当前的price(当天的价格)
1)先把当天的价格插入到vector, (因为股票价格小于或等于今天价格的最大连续日数,跨度都要++,包含当天)
2)定义一个遍历res,记录跨度, 然后从后往前遍历vector,如果price的值大于当前元素arr[i],res++ 直到找到price左侧第一个比price大的元素就break跳出循环, 或者全部元素都比price小
class StockSpanner {
public:
//本题是求 当前位置的元素与「 上一个更大元素」之间的元素个数
//本质是求左边大于price的第一个数的位置和当前price位置的差距
vector<int> arr;
StockSpanner() {
}
int next(int price) {
arr.push_back(price);
int res = 0;//记录跨度
for(int i = arr.size()-1 ;i>=0;i--) //从后往前遍历
{
if(price>=arr[i])
res++;
else //当前arr[i]是price左侧第一个比price大的值
break;
}
return res;
}
};
方法2:单调栈!
求「上/下 」一个更 「大/小」 元素 ->使用单调栈
class StockSpanner {
public:
vector<int> nums;//保存已经添加的元素
stack<int> st;//单调栈,保存的是下标索引,从栈底往栈顶单调递减
int index ;//当前位置的索引
StockSpanner() :index(-1)
{}
int next(int price) {
index++;//price元素对应的下标++
while(!st.empty() && nums[st.top()]<=price)
{
//如果栈顶元素对应的值<=price,不断弹出栈顶元素
st.pop();
}
//直到栈顶元素对应的值>price,此时栈顶其对应的下标就是比price的上一个更大的元素
//price和上一个比它大的元素的下标距离就是res : (st.top(),index]
//如果栈为空,说明前面的所有元素都是比price小的,距离res就是index+1 (因为下标从0开始)
int res = st.empty()?index+1:index-st.top();
//更新单调栈,把当前数加到数组
st.push(index);
nums.push_back(price);
return res;
}
};
判断什么时候应该用单调递增的栈,什么时候应该用单调递减的栈
- 往前走找第一个比自己 大 的元素,用单调递减的栈,也就是出栈的元素要求比自身要大, 也就是st.top() <= price才出栈
- 往前走找第一个比自己 小 的元素,用单调递增的栈,也就是出栈的元素要求比自身要小,也就是 st.top() >= price才出栈