首页 > 其他分享 >1124.表现良好的最长时段

1124.表现良好的最长时段

时间:2023-04-10 15:32:45浏览次数:36  
标签:minStack cur int sum 1124 ret hours 时段 最长


1124.表现良好的最长时段

同类题目

题目描述

 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。请你返回「表现良好时间段」的最大长度。

输入:hours = [9,9,6,0,6,6,9]
输出:3
解释:最长的表现良好时间段是 [9,9,6]。

解题思路

题意剖析:题目意思是对于hours 中的每个元素,大于8记为1,否则记为-1,要我们算标记后的数组中,和大于0的最长区间。

1124.表现良好的最长时段_i++

解法1:暴力

 两重for 循环,但是无法AC。第一重循环用于计算从下标 0,到当前下标 i的前缀和第二重循环用于计算从下标 0,到当前下标 j 的前缀和,两者前缀和的差值若均大于0,则符合条件,此时需要通过判断对返回值 ret 进行更新。

解法2:哈希

 用一个 cur 变量记录前缀和,当大于8时,cur++, 小于8时,cur–。由于从前向后遍历,当 cur > 0时,说明从开始到现在满足条件,时间必然是最长的,直接更新 res = i + 1。当 cur <= 0时呢?关键来了
 这里用一个 字典记录所有 cur <= 0的最小下标,所谓最小,就是后面如果再碰到了同样的 cur,不需要更新,如果没有碰到过,则把这个下标记录下来。然后用 cur - 1 去字典里找,如果找到了下标j,那么就说明从0到 j 的前缀和是 cur-1,而从0到 i 的前缀和是 cur,那么显然从 j 到 i的和是(cur - (cur - 1)) = 1 > 0,也就是说从 j+1到 i 的表现肯定是满足的,并且由于 j 是 cur-1中最小的,所以 i-j 是最大的。此时再跟 res 比较看是否需要更新。
 上面为什么只需要查找 cur-1?因为满足条件的前缀和只能是小于等于cur-1的,也就是说其实也可以查找 cur-2,cur-3…,但是,cur-2的下标一定不可能在 cur-1的下标左边。使用反证法,前提是cur-1代表的是最小下标,那么如果 cur-2在 cur-1左边,而cur-2的左边一定还会有 cur-1出现(cur值是从0开始的),这就和最小下标的前提矛盾了。
 那么问题又来了,如果 cur-1不存在,是否要查找 cur-2,cur-3…呢?也不需要,思路跟上面是一样的,如果 cur-1不存在,cur-2,cur-3…一定也不存在。举个例子,不可能从0跳到-2,-3,而中间没有-1。
 通过上面有理有据的分析,下面的代码就很简单了。

解法3:单调栈

 其思路和哈希方法一致,但由于没有哈希表的开销,因此运行速度大大加快。

代码

//暴力:超时
class Solution {
public:
    int longestWPI(vector<int>& hours) {
        int ret=0;
        int sum=0;
        for(int i=0;i<hours.size();i++){
            sum+=hours[i]>8?1:(-1);
            int tmpSum=0;
            for(int j=0;j<=i;j++){
                if(sum-tmpSum>0){
                    ret=max(ret,i-j+1);
                }
                tmpSum+=hours[j]>8?1:(-1);
            }
        }
        return ret;
    }
};
//哈希表

class Solution {
public:
    int longestWPI(vector<int>& hours) {
        int ret=0;
        unordered_map<int,int> mymap;
        int cur=0;
        for(int i=0;i<hours.size();i++){
            if(hours[i]>8) cur++;
            else cur--;
            if(cur>0) ret=i+1;
            else{
                if(mymap.count(cur-1)) ret=max(ret,i-mymap[cur-1]);
                if(mymap.count(cur)==0) mymap[cur]=i;
            }
        }

        return ret;
    }
};
// 单调栈(单调减)
class Solution {
public:
    int longestWPI(vector<int>& hours) {
        int ret=0;
        vector<int> sum(hours.size()+1,0);
        stack<int> minStack;
        minStack.push(0);
        for(int i=0;i<hours.size();i++){
            sum[i+1]=hours[i]>8?sum[i]+1:sum[i]-1;
            if(sum[minStack.top()]>sum[i+1]) minStack.push(i+1);
        }

        for(int i=sum.size()-1;i>=0;i--){
            while(minStack.size() && sum[i]-sum[minStack.top()]>0){
                ret=max(ret,i-minStack.top());
                minStack.pop();
            }
        }
        return ret;
    }
};


标签:minStack,cur,int,sum,1124,ret,hours,时段,最长
From: https://blog.51cto.com/u_16063698/6181009

相关文章

  • 405 最长公共子序列 线性DP
    视频链接:https://www.bilibili.com/video/BV1EK411K7Eb/ #include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;constintN=1010;intn,m;chara[N],b[N];intf[N][N];intmain(){cin>>n>>m>>......
  • 2389. 和有限的最长子序列
    题目链接:2389.和有限的最长子序列方法:前缀和+二分查找解题思路根据题意,子序列与\(nums\)数组的元素顺序无关,因此可以先对\(nums\)从小到大排序,并计算前缀和\(nums[i]+=nums[i-1]\),此时的\(nums[i]\)表示原来nums数组\([0,i]\)的区间和。那么\(answer[i]=idx+1\),......
  • UVA - 10131 Is Bigger Smarter? 最长上升子序列
    题目大意:给出一系列大象的体重和IQ的数据,要求找出最长的一串,符合大象1的体重大于大象2,而IQ却小于大象2解题思路:设置一个状态量,d[i],表示以第i只大象为终点的符合条件的最大值,则如果符合大象i的体重大于大象j的体重,但IQ却反之且d[i] <d[j]+1,那么d[i] =d[j]+1#include<cst......
  • HDU - 1317 XYZZY (floyd + 最长路)
    题目大意:有一种游戏,游戏里面有N个房间,每个房间有相应的能量值,走入该房间就可以得到相应的能量值现在你要从房间1出发,走到房间N,如果中途能量耗尽了,就表示输了,反之,则为赢解题思路:首先得判断一下能不能到达N,这可以用Floyd去判断如果能直接走到N的话,就算赢,否则判断一下,看是否有正环......
  • 无重复字符的最长子串
    题目描述难度中等给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:s="bbbbb"输出:1解释:因为无重复字符的最长子串是"b",所以其长度为1......
  • HJ92_在字符串中找出连续最长的数字串_技巧
    思路:按照模拟思路,没有技巧地,代码如2。新思路:把非数字转换成空格,使用空格作为标记切片。!!!注意:字符串变更,要用replace()方法生成新字符串!!! 参考高赞答案,重写代码如1:1importsys2a=[]3forlineinsys.stdin:4a.append(line.strip())5foriina:6fo......
  • 51nod 1055 最长等差数列
    1055 最长等差数列基准时间限制:2 秒空间限制:262144 KB分值: 80 难度:5级算法题 收藏 关注例如:13568910121314等差子数列包括(仅包括两项的不列举)1351591336912......
  • 无重复字符的最长子串的长度
    题目链接解题思路假设有个字符串"abcabca"首先读懂题目,字符指的是个单个字母'a''b'这种,子串指的是"ab""abc""abca","ac"不是子串,所以要求是连续的。无重复字符的意思就是指"abc"中没有一样的字符,而"abca"有两个'a'就重复了。最直接的思路是使用滑动窗口,......
  • 华为OD机试 最长的元音字符串
    本期题目:最长的元音字符串题目定义当一个字符串只有元音字母(a,e,i,o,u,A,E,I,O,U)组成,称为元音字符串,现给定一个字符串,请找出其中最长的元音字符串,并返回其长度,如果找不到请返回0,字符串中任意一个连续字符组成的子序列称为该字符串的子串输入一个字符串其长度 0<lengt......
  • 最长连续序列(并查集、数组)、复原 IP 地址(字符串、回溯)、删除链表的倒数第 N 个结
    最长连续序列(并查集、数组)给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)__的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。它的长度为4......