代码随想录 11.18 || 单调栈 LeetCode 739.每日温度、496.下一个更大的元素Ⅰ

单调栈

        单调栈,即栈中存储的元素值单调递增 or 递减,通常用于在一维数组中寻找任意位置元素的右边或者左边第一个更 大 / 小 元素的位置。在遍历过程中,使用单调栈记录遍历过的元素,栈中存放的是元素的下标,而并非元素本身。

739.每日温度

     给定一个整数数组 temperatures,表示每天的温度,返回一个数组 answer,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。计算一维数组 temperatures 中每一个元素与右边第一个最大的元素的距离。

       使用单调栈存储遍历过元素的下标,在遍历过程中可分为三种情况:当前访问元素大于、小于和等于栈顶元素,对应着不同的处理。

        当前访问元素 temperatures[i] > st.top(),说明我们找到了对应 st.top() 为下表的元素右边第一个最大值,temperatures[i]。根据题意要求,结果集中存储的是右边第一个更大元素到该元素的距离,因此 result[st.top()] = i - st.top(),并将栈顶元素出栈。注意,当前访问的元素,可能比栈不止一个元素都大,即它可能是多个元素的右边第一个最大的元素,所以需要使用一个循环进行遍历。直至不符合要求或者栈空,然后将当前元素压栈。从上述操作可以看出,栈顶元素为即将要加入结果集的元素的下标,当前访问的元素为可能符合要求的元素。

        当前访问元素 temperatures[i] < st.top(),说明当前元素不符合要求,直接将当前元素压栈,相等情况同理。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int> &T) {
        int len = T.size();
        auto result = vector<int> (len, 0);

        stack<int> st; 
        st.push(0);

        for (int i = 1; i < len; ++i) {
            if (T[i] <= T[st.top()]) st.push(i);
            else {
                while (!st.empty() && T[i] > T[st.top()]) {
                    result[st.top()] = i - st.top();
                    st.pop();
                }
                st.push(i);
            }
        }

        return result;
    }
};

         下面是精简过后的代码。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int> &T) {
        int len = T.size();

        vector<int> result(len, 0);
        stack<int> st;
        
        for (int i = 0; i < len; ++i) {
            while (!st.empty() && T[i] > T[st.top()]) {
                result[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);
        }

        return result;
    }
};

496.下一个更大的元素Ⅰ

    题干过于复杂,不在此赘述。本题为单调栈经典题目,设有一些变化。数组 nums1 是 nums2 的子集,寻找 num1 中的元素,在 nums2 中右边第一个更大的元素。

        首先是暴力解法,居然通过了,嵌套三个循环,第一个循环用于在 nums1 中挑选元素,第二个循环用于在 nums2 中寻找给定元素的位置,第三个循环用于返回给定元素右起第一个更大的值。在实现上是三层嵌套循环,但是本质上为两层嵌套循环,第三层循环只执行了一次。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int> &nums1, vector<int> &nums2) {
        int len1 = nums1.size(), len2 = nums2.size();

        vector<int> result(len1, -1);

        for (int i = 0; i < len1; ++i) {
            for (int j = 0; j < len2; ++j) {
                if (nums2[j] != nums1[i]) continue;
                for (int k = j + 1; k < len2; ++k) {
                    if (nums2[k] > nums1[i]) {
                        result[i] = nums2[k];
                        break;
                    }
                }
                break;
            }
        }
        
        return result;
    }
};

        单调栈解法,nums1 是 nums2 的子集,那么只要找到 nums2 中所有元素右边第一个更大的元素的值,然后判断该元素在不在 nums1 中,如果在将这个更大的值添加进结果集即可。问题转化为单调栈 + 哈希映射的使用。下面的代码可以如 739.每日温度 进行精简。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int> &nums1, vector<int> &nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        
        vector<int> result(len1, -1);
        if (len1 == 0) return result;

        unordered_map<int, int> umap;
        for (int i = 0; i < len1; ++i) umap[nums1[i]] = i;

        stack<int> st;
        st.push(0);

        for (int i = 1; i < len2; ++i) {
            if (nums2[i] < nums2[st.top()]) st.push(i);
            else if (nums2[i] == nums2[st.top()]) st.push(i);
            else {
                while (!st.empty() && nums2[i] > nums2[st.top()]) {
                    if (umap.count(nums2[st.top()]) > 0) {
                        int index = umap[nums2[st.top()]];
                        result[index] = nums2[i];
                    }
                    st.pop();
                }
                st.push(i);
            }
        }

        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值