LeetCode1124. 表现良好的最长时间段

  1. 表现良好的最长时间段
    给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。

我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。

所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。

请你返回「表现良好时间段」的最大长度。

示例 1:

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

理解:题中所求的是 「劳累的天数」 大于「不劳累的天数」 ,设大于8(即劳累)的值为1,小于8(不劳累)的值为-1,则总的来说就是求最长连续字串的和大于0.

法1:暴力
按照上面的思路先将其用1和-1表示每一天的状态赋值到一个新的数组a[]中。再通过遍历,每次比较 max = Math.max(max, j - i + 1);从而得到max的最大值,return max即可

class Solution {

    public int longestWPI(int[] hours) {

        int n = hours.length;
        int[] a = new int[n];
        int sum = 0;
        int max = 0;

        for (int i=0;i<n;i++) {

            if (hours[i] > 8) {

                a[i] = -1;
            } else {

                a[i] = 1;
            }
        }

        for (int i=0;i<n;i++) {

            for (int j=i;j<n;j++) {

                sum += a[j];
                if (sum < 0) {

                    max = Math.max(max, j - i + 1);
                }
            }
            sum = 0;
        }
        return max;
    }
}


法二,前缀和+单调栈
仍然先将其按照1和-1的方式赋值到score[]数组中,再由score数组得到前缀和presum数组,其中前缀和是指不含当前下标的值的前缀相加,所以这里的presum数组大小为n+1,比hours的数组大小要大1.
hours = [9,9,6,0,6,6,9]为例子,score = [1, 1, -1, -1, -1, -1, 1],然后我们对得分数组计算前缀和 presum = [0, 1, 2, 1, 0, -1, -2, -1]。因为要寻找的是大于0的最长,然后我们用一个单调递减栈stack来存储presum中的单调递减的下标,其中单调递减栈是指栈中元素按照从栈顶到栈底的顺序依次递减。这里发现presum = [0, 1, 2, 1, 0, -1, -2, -1]中递减的值为0,-1,-2,其对应的下标分别为0,5,6.故将其下标0,5,6分别压入栈。这时候再将presum中的元素的值由后到前与栈中元素下标在presum中对应的值进行比较。presum[i] > presum[stack.peek()],如果满足该条件则表示当前i到stack.peek()之间是满足条件的。依此类推。如果不满足该条件,则出栈。

class Solution {

    public int longestWPI(int[] hours) {

        int n = hours.length;
        int[] score = new int[n];
        for (int i=0;i<n;i++) {

            if (hours[i] > 8) score[i] = 1;
            else score[i] = -1;
        }

        int[] presum = new int[n + 1];
        presum[0] = 0;
        for (int i=1;i<n+1;i++) {

            presum[i] = presum[i - 1] + score[i - 1];
        }
        
        int result = 0;
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(0);
        for (int i=1;i<n+1;i++) {

            if (stack.isEmpty() || presum[stack.peek()] > presum[i]) {

                stack.push(i);
            }
        }
        for (int i=n;i>=0;i--) {

            while(!stack.isEmpty() && presum[i] > presum[stack.peek()]) {

                result = Math.max(result, i - stack.pop());
            }
        }
        return result;
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超好的小白

没体验过打赏,能让我体验一次吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值