一、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
方法一:排序
根據數組的權值排序數組所在下標,這樣就能快速地找到當前位置 之前最小下標 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 表達式的 []
中寫 =
和 &
的區別,寫 =
會超時
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:單調棧
思路
我們希望在遍歷某一個元素 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;
}
};
複雜度分析
- 時間複雜度:,
- 空間複雜度:,