Leetcode 1124. Longest Well-Performing Interval
Woodyiiiiiii opened this issue · comments
首先预处理数组,大于8小时的标志为1,否则则为-1,从而形成前缀和数组。
方法一:单调栈+前缀和+逆序遍历
对于某个位置i,要找到位于最左边的j,使得前缀和[0,i]-[0,j]大于0。如果正序遍历,会出现漏算的情况,所以需要逆序遍历。而且,一开始将0压入栈中。
class Solution {
public int longestWPI(int[] hours) {
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.offer(0);
int n = hours.length;
int[] pre = new int[n + 1];
for (int i = 1; i <= n; ++i) {
int t = hours[i - 1] > 8 ? 1 : -1;
pre[i] = pre[i - 1] + t;
if (!stack.isEmpty() && pre[i] < pre[stack.peek()]) {
stack.push(i);
}
}
int ans = 0;
for (int i = n; i >= 1; --i) {
while (!stack.isEmpty() && pre[stack.peek()] < pre[i]) {
ans = Math.max(ans, i - stack.pop());;
}
}
return ans;
}
}
方法二:哈希+前缀和+贪心
对于前缀和[0,i]大于0的情况,显然最左的j是0;否则找到[0,i] - 1出现的位置。因为整个数组可以画成具有连续性的函数。
class Solution {
public int longestWPI(int[] hours) {
Map<Integer, Integer> map = new HashMap<>();
int n = hours.length;
int[] pre = new int[n + 1];
for (int i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + (hours[i - 1] > 8 ? 1 : -1);
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
if (pre[i] > 0) {
ans = Math.max(ans, i);
} else {
ans = Math.max(ans, i - map.getOrDefault(pre[i] - 1, i));
}
if (!map.containsKey(pre[i])) {
map.put(pre[i], i);
}
}
return ans;
}
}