Leetcode 1124. Longest Well-Performing Interval 前缀和数组+hashmap好题

  1. Longest Well-Performing Interval
    Medium
    1.3K
    105
    Companies
    We are given hours, a list of the number of hours worked per day for a given employee.

A day is considered to be a tiring day if and only if the number of hours worked is (strictly) greater than 8.

A well-performing interval is an interval of days for which the number of tiring days is strictly larger than the number of non-tiring days.

Return the length of the longest well-performing interval.

Example 1:

Input: hours = [9,9,6,0,6,6,9]

Output: 3

Explanation: The longest well-performing interval is [9,9,6].

Example 2:

Input: hours = [6,6,6]

Output: 0

Constraints:

1 <= hours.length <= 104

0 <= hours[i] <= 16

解法1:presums[] + hashmap。

  1. 先归一化数组。> 8 ->1, <=8 ->-1。这样题目就变成了求最长和>0的子数组。
  2. hashmap存储<presum, index>,这里index是presum出现最早的位置。
  3. 当presums[i] > 0时,即为一个解。
  4. 当presums[i]<=0时,我们找presums[i]-1的那个对应位置即可。
    为什么这个是正确的。举例如下:当presum变成-3时,我们找presum变成-4的最开始的那个位置即可。这里有两种可能性,用 i - mp[presums[i] - 1]都是正确的。
    presum变化可能1: 0->-1->-2->-3>-4>-5->-4->-3

    presum变化可能2: 0->-1->-2->-3->-4->-3
cpp 复制代码
class Solution {
public:
    int longestWPI(vector<int>& hours) {
        int n = hours.size();
        vector<int> presums(n + 1, 0);
        unordered_map<int, int> mp; //<presum, index>
        int res = 0;
        for (int i = 1; i <= n; i++) {
            presums[i] = presums[i - 1] + (hours[i - 1] > 8 ? 1 : -1);
        }
        mp[0] = 0;
        for (int i = 1; i <= n; i++) {
            if (presums[i] > 0) {
                res = max(res, i);
            } else {
                if (mp.find(presums[i] - 1) != mp.end()) {
                    res = max(res, i - mp[presums[i] - 1]);
                }
            }
            if (mp.find(presums[i]) == mp.end()) mp[presums[i]] = i;
        }
        return res;
    }
};

解法2:滑动窗口?

我感觉这题不能用滑动窗口。

比如说[6,6,6,9,9,9,9,6,6,6,6,6,9,9,9,9,9,9,9,9],一开始都是<=8的,后来又是>8的,然后又是<=8的,然后又是>8的。最优值就是数组长度n。如果要求最大的窗口范围,则right边界从左到右移动完整个数组的时候,left边界都不能移动,一动就错。

我个人的想法:用滑动窗口的场合需要具备某种单调性?那就是如果小窗口符合这个条件,那么包含小窗口的大窗口肯定也符合这个条件。但是这题好像不是,比如说小窗口是>8的数字多,那未必大窗口就是>8的数字多啊。欢迎大家指教。

新想法:为什么不能用滑动窗口呢?因为滑动窗口必须满足目标值的某种单调性,即右边界加入数据,目标值一定会变大或至少不变,左边界移除数据,目标值一定会变小或至少不变,这里的目标值可能是无重复数据的窗口大小等等。这题右边界扩大,有可能是合法的窗口变大,比如说6,9,9变到6,9,9,9,但也可能是合法窗口变小,比如说6,9,9变到6,9,9,6。当我们发现合法窗口变小时,我们也不能移动左窗口,因为实际数据可能是6,9,9,6,9,9,9。

注意:为什么这题可以不可以用滑动窗口,而Leetcode 1004. Max Consecutive Ones III这题就能用呢?

因为Leetcode 1004的滑动窗口满足单调性,即右指针移动直到当前窗口不合格时(即flipCount>k),再移动右指针,当前窗口肯定还是不合格(因为flipCount还是>k)。而这题里面,当我们移动右指针直到当前窗口不合格时(即>8小时的天数小于等于<=8小时的天数),再移动右值时,当前窗口可能又合格了,因为又加入了更多的>8小时的天数。

另外,如果不能用滑动窗口,那我们还是可以用前缀和数组+hashmap来处理。

解法3:单调栈。

注意单调栈是求数组左右侧第一个大于或小于该数的位置。

相关推荐
Java技术实践17 分钟前
JPA 用 List 入参在 @Query中报错 unexpected AST node: {vector}
数据结构·windows·list
陌路2017 分钟前
S4双向链表
数据结构·链表
再卷也是菜36 分钟前
C++篇(14)二叉树进阶算法题
c++·算法
小邓儿◑.◑40 分钟前
贪心算法 | 每周8题(三)
算法·贪心算法
2401_8414956443 分钟前
【数据结构】最长的最短路径的求解
java·数据结构·c++·python·算法·最短路径·图搜索
泡沫冰@1 小时前
数据结构(5)
数据结构
小龙报1 小时前
《算法每日一题(1)--- 连续因子》
c语言·开发语言·c++·windows·git·算法·visual studio
第七序章1 小时前
【C + +】红黑树:全面剖析与深度学习
c语言·开发语言·数据结构·c++·人工智能
夜晚中的人海1 小时前
【C++】滑动窗口算法习题
开发语言·c++·算法
violet-lz2 小时前
数据结构四大简单排序算法详解:直接插入排序、选择排序、基数排序和冒泡排序
数据结构·算法·排序算法