【算法總結】單調棧或隊列


單調棧

  單調棧,就是一個棧,里面的元素滿足一定的單調性。(多見於單調增/單調減)

1)新元素加入棧前,會在棧頂端把破壞棧單調性的元素都刪除,直到棧為空或者棧滿足單調性才能加入新元素。

2)單調棧是 O(n) 級的時間復雜度,所有元素只會進入棧一次,並且出棧后再也不會進棧。

3)單調棧可以找到元素向左遍歷第一個比他小(大)的元素,也就是說在元素進棧前他向左拓展的區間已經確定,在出棧前她能向右拓展的區間也能確定(左區間好理解,仔細體會右區間的確定,若該元素至遍歷結束后也未出棧,那么就是說在原數組中,該元素的右方向沒有一個元素可以比它大/小,那么該元素的右邊界就是原數組的大小(就是沒有右邊界),否則它的右邊界就是令它出棧的元素)。

例1

題目描述:

  給定一個數組,返回一個大小相同的數組。返回的數組的第i個位置的值應當是,對於原數組中的第i個元素,至少往右走多少步,才能遇到一個比自己大的元素(如果之后沒有比自己大的元素,或者已經是最后一個元素,則在返回數組的對應位置放上-1)

Example:

Input

5,3,1,2,4

Output

-1 3 1 1 -1

Solution

#include <iostream>
#include <vector>
#include <stack>

using namespace std;

vector<int> stepToGreater(vector<int> &nums){
    int n = nums.size();
    if (n < 1)
        return{};
    nums.push_back(INT_MIN);
    vector<int> res(n, -1);
    stack<int> s;
    for (int i = 0; i <= n; ){
        if (s.empty() || nums[s.top()] >= nums[i])
            s.push(i++);
        else {
            int cur = s.top();
            s.pop();
            res[cur] = i - cur;
        }
    }
    nums.pop_back();
    return res;
}
int main(){
    vector<int> v{ 5, 3, 1, 2, 4 };
    vector<int> res = stepToGreater(v);
    for (auto n : res){
        cout << n << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

例2:【LeetCode】084. Largest Rectangle in Histogram

 

  通常來講,單調棧更傾向於一維數組的問題,或者是多維數組可以轉化為一維數組的問題。多存儲元素坐標而非元素值。問題多見於尋找數組元素左區間或右區間最大最小問題,或者找出元素的兩邊界問題。

單調隊列

  單調隊列其實和單調棧差不多,一個思想:棧或隊列中元素滿足單調性,當有新元素要入棧或者入隊的時候,要和棧頂或者隊尾元素進行比較,滿足單調的性質則入隊或入棧,否則將棧頂或隊尾元素刪去,直到滿足單調性質,然后將新元素入隊或入棧。

例題:【隊列】滑動窗口的最大值,類似的還有求最小值問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM