496. Next Greater Element I

问题:

给定数组num2,

求num1中各数右边第一个大于它的数。

Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
Output: [-1,3,-1]
Explanation:
For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
For number 1 in the first array, the next greater number for it in the second array is 3.
For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4]
Output: [3,-1]
Explanation:
For number 2 in the first array, the next greater number for it in the second array is 3.
For number 4 in the first array, there is no next greater number for it in the second array, so output -1.
 

Constraints:
1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 10^4
All integers in nums1 and nums2 are unique.
All the integers of nums1 also appear in nums2.

  

解法:Monotonic stack(单调栈)

参考:单调栈&单调队列详解

 

对单调栈or队列的pop操作都在:尾部stack.top & queue.back<因此得用deque,而不用queue>)

❤️  !!POINT

  • 动作:要插入新元素
  • 要求:要保持栈or队列的状态为递增(递减)
    • 不满足要求:则pop已有元素,再插入当前元素。

特点:

  • <常用🌟 >单调递增 栈 (递减队列->可求区间最大值front)(front)<-[4,3,2,1<-top(back)
    • 保存离现在cur最近index为止,最大值递增序列
  • 单调递减 栈 (递增队列->可求区间最小值front)(front)<-[1,2,3,4<-top(back)
    • 保存离现在cur最近index为止,最小值递减序列

 

增减性 定义:

  • stack
    • 单调 栈:top->bottom 递增↗️     [4,3,2,1<-top
      • while( !stack.empty() && stack.top<=cur ) pop
      • stack.push(cur)
    • 单调 栈:top->bottom 递减↘️     [1,2,3,4<-top
      • while( !stack.empty() && stack.top>=cur ) pop
      • stack.push(cur)

 解说:

具体进栈过程
对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。
对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

  

  • deque(固定capacity)
    • 单调 队列:front->back 递增↗️     <-[1,2,3,4]<-back
      • while( !deque.empty() && deque.back>=cur ) pop_back
      • deque.push_back(cur)
    • 单调 队列:front->back 递减↘️     <-[4,3,2,1]<-back
      • while( !deque.empty() && deque.back<=cur ) pop_back
      • deque.push_back(cur)

 解说:

具体入队过程
对于单调递增队列,设当前准备入队的元素为e,从队尾开始把队列中的元素逐个与e对比,把比e大或者与e相等的元素逐个删除,直到遇到一个比e小的元素或者队列为空为止,然后把当前元素e插入到队尾。
对于单调递减队列也是同样道理,只不过从队尾删除的是比e小或者与e相等的元素。

  

可求解问题:(例如:单调增栈 [4,3,2,1<-3)需要pop 1, 2, 3

两个方向:

  • 当前元素 (cur=3)
    • 左边区间,第一个>cur的数 4。
  • 被弹出的元素 stack.top (1,2,3)
    • 右边第一个>=自己的数 cur=3。

单调队列:

  • 单调减 front->back 递减↘️     <-[4,3,2,1]<-back
    • 区间最大值:front
  • 单点增 front->back 递增↗️     <-[1,2,3,4]<-back
    • 区间最小值:front

参考例题:239. Sliding Window Maximum 

 

本题解法:

要求每个元素右边第一个>自己的数。

有上面的思路,我们可以站在被弹出元素的角度,

使用单调递增栈,来解决。

 

另,求num1中对应num2中的各个元素num。

可引入unordered_map来解决对应关系。

  • key:num
  • value:所求下一个更大元素。

 

代码参考:

 1 class Solution {
 2 public:
 3     vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
 4         unordered_map<int, int> mp;//num_value:res
 5         vector<int> res;
 6         stack<int> s;
 7         for(int n:nums2) {
 8             while(!s.empty() && s.top()<n) {
 9                 mp[s.top()]=n;
10                 s.pop();
11             }
12             s.push(n);
13         }
14         for(int n1:nums1) {
15             res.push_back(mp.count(n1)?mp[n1]:-1);
16         }
17         return res;
18     }
19 };

 

posted @ 2021-04-16 15:26  habibah_chang  阅读(37)  评论(0编辑  收藏  举报