【棧】B020_LC_最大寬度坡(排序 / 單調棧)

一、Problem

給定一個整數數組 A,坡是元組 (i, j),其中 i < j 且 A[i] <= A[j]。這樣的坡的寬度爲 j - i。

找出 A 中的坡的最大寬度,如果不存在,返回 0 。

輸入:[6,0,8,2,1,5]
輸出:4
解釋:
最大寬度的坡爲 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.

提示:

2 <= A.length <= 50000
0 <= A[i] <= 50000

二、Solution

方法一:排序

根據數組的權值排序數組所在下標,這樣就能快速地找到當前位置 ii 之前最小下標 mi,且 mi 位置的權值比當前位置的權值要小

class Solution {
public:
    int maxWidthRamp(vector<int>& A) {
    	int n = A.size();
    	vector<int> B(n);
    	for (int i = 0; i < n; i++) B[i] = i;
    	sort(B.begin(), B.end(), [&](int a, int b){
            if (A[a] == A[b])
                return a < b;
            return A[a] < A[b];
        });

    	int mi = n, ans = 0;
    	for (int idx : B) {
    		ans = max(ans, idx-mi);
    		mi = min(mi, idx);
    	}
    	return ans;
    }
};

C++ 新手,不是很懂 lambda 表達式的 [] 中寫 =& 的區別,寫 = 會超時

複雜度分析

  • 時間複雜度:O(nlogn)O(nlogn)
  • 空間複雜度:O(n)O(n)

方法二:單調棧

思路

我們希望在遍歷某一個元素 A[i] 時,能快速地找到一個比A[i] 小的,且在 i 位置左邊的元素,基於這一點,我們可維護一個權值對應的下標單調遞減的棧

我們希望坡度最大,所以我們從右往左枚舉,這樣可以儘量讓我們計算得到的結果最大

細節:噹噹前遍歷下標 i 小於當前最大坡度 ans,那麼無論棧中元素是多少,產生的新坡度都不會大於 ans,故可提前結束遍歷

class Solution {
public:
    int maxWidthRamp(vector<int>& A) {
    	int n = A.size(), ans = 0;
    	stack<int> st;
    	for (int i = 0; i < n; i++) {
    		if (st.empty() || A[i] <= A[st.top()]) 
                st.push(i);
    	}
    	for (int i = n-1; i > ans; i--) {
    		while (!st.empty() && A[st.top()] <= A[i]) {
    			ans = max(ans, i - st.top()); st.pop();
    		}
    	}
    	return ans;
    }
};

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章