題目鏈接:556. 下一個更大元素 III
(由于圖片上傳失敗,不貼原題目了,有需要可以前往力扣查看)
本文給出該題的單調棧做法,同時繞過所有庫函數,所有邏輯均自行實現。
本題的思路就是從右向左按位遍歷,找到第一次下降時的下標,同時將數字對于下標填入棧中。這樣,當找到要更改的下標時,開始循環,找到最后一個比要被替換的數字大的值,這就是單調棧。互換二者位置。我們假設第一次下降時下標為 idx , 被替換下標為 change, 由之前邏輯可以知道,[idx + 1, change - 1]的數字均大于idx的數字,[change + 1, size - 1]位置的數均小于idx的數字,最后我們只需要將[idx + 1, size - 1]位置的所有數字調換順序就保證為下一個更大的數字,而不必使用排序。
而以上所需的交換swap,逆序reverse,還有離散化數字和重組數字,代碼都給予實現。
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]){// 找到第一次下降的下標 iint 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;}
};