【LeetCode】每日一题:下一个更大元素——2023.12.12

题目链接:下一个更大元素

题干解读:

题意很简单,给你一个数组nums,你需要返回一个数组ans,其中ans[i]为nums[i]后方第二个比nums[i]的数,若不存在,则ans[i]为-1;

解题思路:

这个题需要用到单调栈的概念,考虑一个更简单的情况:如果我们只需要获取每个数后面第一个比它大的数,则我们只需要用一个单调栈st对数组下标进行维护,对数组进行遍历:

(1)若当前遍历到的数nums[i]大于栈顶对应的数nums[st.top()],则栈顶的下标出栈st.pop(),该第一个比该下标处大的数即当前遍历到的数ans[st.top()]=nums[i],重复该步骤;

(2)将当前遍历到的下标i压入栈中。

而对于该题,我们需要获取第二个大的数,也就是说我们可以把数组中每个数都想象成有两条命,当有遍历到有一个数大于他,则扣除一条命,当它的命扣完时,将它的命扣完的那个数就是第二个比他打的数。和上述步骤相似,我们用一个单调栈st对有两条命的数的下标进行维护,采用一个小顶堆q对有一条命的数的值(需要借助值进行小顶堆排序)和下标进行维护,遍历数组nums:

(1)若nums[i]大于堆顶的数的值,则nums[i]就是堆顶处这个数的第二大数字,堆顶数字出队,重复该步骤,直到堆为空或者nums[i]不大于堆顶处的数。

(2)若nums[i]大于栈顶的下标对应的数,则该数扣除一条命,将该数及其下标加入小顶堆,栈顶出栈,重复该步骤,直至栈为空或nums[i]不大于栈顶处的数。

(3)将当前遍历到的数的下标压入栈中。

这个思路可以扩充至找第n个大的数。

同时这个题中可以发现进行步骤(1)后堆中最小的数>nums[i],而进行(2)时会将栈中所有小于nums[i]的数都压入堆中(小的数先入堆),因此只要保证第(2)步中将数压入堆的时候保持栈中的顺序,即可以采用一个单调栈来代替堆(无需进行额外的排序,减小时间复杂度)

class Solution {
public:
    vector<int> secondGreaterElement(vector<int>& nums) {
        stack<int> st;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
        vector<int> ans(nums.size(), - 1);
        for(int i = 0; i < nums.size(); i ++){
            while(!q.empty() && nums[i] > q.top().first){
                ans[q.top().second] = nums[i];
                q.pop();
            }
            while(!st.empty() && nums[i] > nums[st.top()]){
                q.push({nums[st.top()], st.top()});
                st.pop();
            }
            st.push(i);
        }

        return ans;
    }
};

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值