題目:
給定一個整數序列:a1, a2, ..., an,一個132模式的子序列 ai, aj, ak 被定義爲:當 i < j < k 時,ai < ak < aj。設計一個算法,當給定有 n 個數字的序列時,驗證這個序列中是否含有132模式的子序列。
注意:n 的值小於15000。
示例1:
輸入: [1, 2, 3, 4]
輸出: False
解釋: 序列中不存在132模式的子序列。
示例 2:
輸入: [3, 1, 4, 2]
輸出: True
解釋: 序列中有 1 個132模式的子序列: [1, 4, 2].
示例 3:
輸入: [-1, 3, 2, 0]
輸出: True
解釋: 序列中有 3 個132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].
題解:
這道題的關鍵是從後往前遍歷,爲什麼呢?因爲題目轉換爲我們要找到1,而1最可能就是在最前面出現的,作爲座標最小值也最小的數,因此更大的數3和2就從後面開始遍歷。因爲3和2的值越大越好。因此使用了遞減棧,遞減棧的作用是棧頂就是我們現在找到的最大的3,棧中的其他數雖然是大於3的,但是 不可能作爲3,因爲它們更可能是作爲
[2 3 4]
這樣的遞減數組被加進來的,它們沒有符合座標比它們大,值又比它們小的2,因此就被壓棧了。但是遍歷時一旦發現有值比棧頂大,說明3值可以得到更新,更重要的是,它打破了遞減數列,說明2是真實存在的,這也是2初始值爲INT_MIN的原因。2當然也是越大越好,因此它就取值爲被替換的3的舊值,剛好保證是次小於3的。
代碼:
class Solution {
public:
bool find132pattern(vector<int>& nums) {
int second = INT_MIN;
stack<int>s;
for(int i = nums.size()-1;i>=0;i--)
{
if(nums[i] < second) return true;
while(!s.empty() && nums[i] > s.top())
{
second = s.top();
s.pop();
}
s.push(nums[i]);
}
return false;
}
};