單調棧
單調棧,就是一個棧,里面的元素滿足一定的單調性。(多見於單調增/單調減)
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
通常來講,單調棧更傾向於一維數組的問題,或者是多維數組可以轉化為一維數組的問題。多存儲元素坐標而非元素值。問題多見於尋找數組元素左區間或右區間最大最小問題,或者找出元素的兩邊界問題。
單調隊列
單調隊列其實和單調棧差不多,一個思想:棧或隊列中元素滿足單調性,當有新元素要入棧或者入隊的時候,要和棧頂或者隊尾元素進行比較,滿足單調的性質則入隊或入棧,否則將棧頂或隊尾元素刪去,直到滿足單調性質,然后將新元素入隊或入棧。
例題:【隊列】滑動窗口的最大值,類似的還有求最小值問題。
