LeetCode 739. 每日温度
思路:
题目要求找到为给定数组提供数组中下一个大于该数字的位置,暴力算法是两个循环遍历数组然后记录下大于当前数的第一个数,但还有更聪明的做法。利用从代码随想录摘抄的一句话:
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。
所以本题适用单调栈。具体思路为,建立一个从栈顶到栈底单调递增的栈,然后遍历数组,每次都按照栈的单调性往栈里面放元素,当栈顶元素小于当前元素的时候,将栈顶元素pop出来,并为栈顶元素记录下当前元素,当前元素即为栈顶元素对应的第一个比自己大的元素。通过这种方法可以为所有被弹出的栈顶元素找到第一个比自己大的元素,如果还有元素在栈里面,说明后面没有比自己大的元素了。
解决这道题的核心思想就是确认单调栈的单调性,是从小到大还是从大到小。题目要找比自己大的元素,当栈内元素遇到比自己大的元素,就可以弹出并记录,所以栈顶元素一定是最小的。同理可得,如果题目要求找第一个比自己小的元素,栈顶到栈底就该是由大到小排列。
其次是确认栈内储存的元素是什么,在这题当中,我们应该储存当前元素的下标,这样当遇到了比自己大的元素,利用下标就可以算出下一个比自己大的元素在什么位置。
代码:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
vector<int> ans(temperatures.size());
// 单调栈
stack<int> st;
for (int i = 0; i < temperatures.size(); i++)
{
// 单调递增
while (!st.empty() && temperatures[st.top()] < temperatures[i])
{
ans[st.top()] = i - st.top();
st.pop();
}
st.push(i);
}
return ans;
}
};
LeetCode 496.下一个更大元素 I
思路:
其实和上一题是非常相似的,但是这题有两点不同。1、由一个数组变成了两个数组。2、寻找的下一个更大元素不是下标了而是元素的值。同样还是用栈顶到栈底单调递增的单调栈,但是为了满足O(n)的复杂度,在遍历nums2并把元素放入栈里的时候,弹出栈顶时要寻找nums1是否有对应的元素,如果有,就记录下来对应的nums1里的元素在nums2里的下一个更大元素是多少。为了方便查找,我们需要一个哈希表,key为nums1的值,value为nums1的值的下标。通过nums1的值在哈希表里找是否有对应元素,然后根据下标在ans里记录下nums2里下一个更大元素是多少。
代码:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> hashmap;
stack<int> st;
vector<int> ans(nums1.size(), -1);
for (int i = 0; i < nums1.size(); i++)
hashmap[nums1[i]] = i;
for (int i = 0; i < nums2.size(); i++)
{
// 检查单调堆顶元素是否小于当前元素
while (!st.empty() && nums2[i] > st.top())
{
// 在哈希表中寻找堆顶元素
auto it = hashmap.find(st.top());
// 记录堆顶元素的下一个更大元素
if (it != hashmap.end())
ans[it->second] = nums2[i];
st.pop();
}
// 将当前元素插入单调堆
st.push(nums2[i]);
}
return ans;
}
};