Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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;
    }
}