Leetcode——556. 下一个更大元素 III

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

(由于图片上传失败,不贴原题目了,有需要可以前往力扣查看)

本文给出该题的单调栈做法,同时绕过所有库函数,所有逻辑均自行实现。

本题的思路就是从右向左按位遍历,找到第一次下降时的下标,同时将数字对于下标填入栈中。这样,当找到要更改的下标时,开始循环,找到最后一个比要被替换的数字大的值,这就是单调栈。互换二者位置。我们假设第一次下降时下标为 idx , 被替换下标为 change , 由之前逻辑可以知道,[idx + 1, change - 1] 的数字均大于idx的数字,[change + 1, size - 1] 位置的数均小于idx 的数字,最后我们只需要将**[idx + 1, size - 1]**位置的所有数字调换顺序就保证为下一个更大的数字,而不必使用排序。

而以上所需的交换swap ,逆序reverse,还有离散化数字和重组数字,代码都给予实现。

cpp 复制代码
class Solution {
public:
    int nextGreaterElement(int n) {
        int cnt = 0;    // 位数
        vector<int> nums;   // 离散化
        for(int i = n; i > 0; i /= 10){
            nums.push_back(i % 10);
            cnt++;
        }
        reverse(0, cnt - 1, nums);    // 更直观
        stack<int> stk;
        stk.push(cnt - 1);
        for(int i = cnt - 2; i >= 0; i--){
            if(nums[i] < nums[i + 1]){
                // 找到第一次下降的下标 i
                int change;        // 被更换位置
                while(!stk.empty() && nums[i] < nums[stk.top()]){
                    change = stk.top();
                    stk.pop();
                }
                swap(i, change, nums);
                reverse(i + 1, cnt - 1, nums);    // 注意下标
                long long ans = funcToll(nums);
                if(ans > INT_MAX){
                    return -1;
                }else{
                    return (int)ans;
                }
            }
            stk.push(i);    // 别忘在没找到前将下标入栈备用
        }
        return -1;
    }

    // 逆序
    void reverse(int i, int j, vector<int>& nums){
        if(i < 0 || j >= nums.size() || i >= j) { return; }
        while(i < j){
            swap(i++, j--, nums);
        }
    }

    // 交换
    void swap(int i, int j, vector<int>& nums){
        if(i < 0 || i >= nums.size() || j < 0 || j >= nums.size()) { return; }
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }

    // 重组数字
    long long funcToll(vector<int>& nums){
        long long ans = 0;
        for(int x : nums){
            ans = ans * 10 + x;
        }
        return ans;
    }
};