给定一个整数数组 A
,坡是元组 (i, j)
,其中 i < j
且 A[i] <= A[j]
。这样的坡的宽度为 j - i
。
找出 A
中的坡的最大宽度,如果不存在,返回 0 。
示例 1:
输入:[6,0,8,2,1,5]
输出:4
解释:
最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.
示例 2:
输入:[9,8,1,0,1,9,4,0,4,1]
输出:7
解释:
最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1.
提示:
2 <= A.length <= 50000
0 <= A[i] <= 50000
看到这道题目,首先想到的方法是记忆化搜索,用递归的方法去寻找最大的坡度
private int[][] memo;
public int maxWidthRamp(int[] A) {
memo = new int[A.length][A.length];
return getMax(A, 0, A.length - 1);
}
private int getMax(int[] A, int left, int right) {
if (left >= right) {
return 0;
}
if (A[left] <= A[right]) {
return right - left;
}
if (memo[left][right] != 0) {
return memo[left][right];
}
memo[left][right] = Math.max(getMax(A, left + 1, right), getMax(A, left, right - 1));
return memo[left][right];
}
然鹅超出了内存限制..
改用滑动模块的方式,从最大长度依次减1去寻找
public int maxWidthRamp(int[] A) {
int i = A.length - 1;
while (i > 0) {
int left = 0;
int right = i;
while (right < A.length) {
if (A[left] <= A[right]) {
return right - left;
} else {
left++;
right++;
}
}
i--;
}
return 0;
}
然鹅超时..
改用单调栈
public int maxWidthRamp(int[] A) {
Stack<Integer> stack = new Stack<>();
int res = 0, n = A.length;
for (int i = 1; i < n; i++) {
if (stack.isEmpty() || A[stack.peek()] > A[i]) {
stack.push(i);
}
}
for (int i = n - 1; i >= res; i--) {
while (!stack.isEmpty() && A[stack.peek()] <= A[i]) {
res = Math.max(res, i - stack.peek());
stack.pop();
}
}
return res;
}
AC,100%
python版本
def maxWidthRamp(self, A):
stack = []
res = 0
for i in range(len(A))[::-1]:
if not stack or A[i] > stack[-1][0]:
stack.append([A[i], i])
else:
j = stack[bisect.bisect(stack, [A[i], i])][1]
res = max(res, j - i)
return res