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:单调栈。

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

相关推荐
锅挤1 小时前
数据结构复习(第四章):串
数据结构
B325帅猫-量子前沿技术研究所1 小时前
PSD和FFT的关系
人工智能·算法
闻缺陷则喜何志丹1 小时前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
avocado_green1 小时前
【LeetCode】90. 子集 II
算法·leetcode
tankeven1 小时前
HJ178 【模板】双指针
c++·算法
君义_noip1 小时前
信息学奥赛一本通 4131:【GESP2506六级】学习小组 | 洛谷 P13015 [GESP202506 六级] 学习小组
算法·动态规划·gesp·信息学奥赛
XS0301061 小时前
数据结构-哈夫曼树,红黑树,B树
数据结构·b树
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 72. 编辑距离 | C++ 经典 DP 增删改状态转移
c++·算法·leetcode
穿条秋裤到处跑2 小时前
每日一道leetcode(2026.04.16):距离最小相等元素查询
算法·leetcode·职场和发展
XY_墨莲伊3 小时前
【实战项目】基于B/S结构Flask+Folium技术的出租车轨迹可视化分析系统(文末含完整源代码)
开发语言·后端·python·算法·机器学习·flask