表现良好的最长时间段

本文介绍了如何通过计算前缀和来解决寻找员工表现良好时间段最大长度的问题。首先将原数据转化为1和-1的数组,然后构建前缀和数组。接着,使用哈希表记录前缀和数组中每个值出现的位置和表现良好的区间的长度。通过遍历前缀和数组,实时计算表现良好的区间长度并更新最长长度。最终返回最长表现良好时间段的长度。提供的C++和Python代码详细展示了实现过程。
摘要由CSDN通过智能技术生成

表现良好的最长时间段

题目

(1)给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。
(2)我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。
(3)所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。
(4)请你返回「表现良好时间段」的最大长度。
(5)示例如下:
输入:hours = [9,9,6,0,6,6,9]
输出:3
解释:最长的表现良好时间段是 [9,9,6]。

解决思路

  • 题意理解:题意求表现良好的最长时间段即在原数组O中找到最长的一段,且该段的和大于0。具体方法是在前缀和数组中,在某一个值 a 的前面找到比 a 小的值 b,使得a - b > 0,且从 a 到 b 的区间最长。
  • 第一步:遍历原数组O,将原数组O转换为由1和-1构成的数组A(当该天表现良好时为1,表现不良好时为-1)。再将数组A转换成前缀和数组B(前缀和数组的作用:能快速计算出数组A的某个区间和,如数组A中从位置 i 到 j 的区间和等于B[j] - B[i])。
  • 第二步:遍历前缀和数B,查看前缀和数组中的每个值cnt在之前是否出现过。若没出现过,则设置cnt第一次出现的位置。
  • 第三步:如果cnt在之前没有出现过,则计算cnt第一次出现时,以cnt作为结尾且表现良好的区间的长度。
  • 第四步:实时计算以 前缀和数组中的每个值作为结尾时,表现良好的区间的长度,并更新最长的长度。
  • 上述步骤如下图所示:
    在这里插入图片描述

代码

  • C++代码
# include <stdio.h>
# include <vector>
# include <unordered_map>
# include <algorithm>

using namespace std;


class Solution {
public:
    int longestWPI(vector<int>& hours) {
        unordered_map<int, int> idx;    // 使用哈希表记录前缀和数组中每种值第一次出现的位置。
        unordered_map<int, int> f;      // 记录前缀和数组中,每个值n第一次出现时,以n作为结尾且表现良好的区间的长度。
        idx[0] = -1;                    // 前缀和数组的第一个元素为0,并将其下标为设置为-1。
        f[0] = 0;                       // 初始化以前缀和数组的第一个元素0作为结尾,且表现良好的区间的长度为0
        int cnt = 0;                    // 用于计算前缀和数组中每个位置的值。
        int answer = 0;
        
        for (int i = 0; i < hours.size(); i++) {
            // 第一步:计算前缀和数组中的每个值。
            if (hours[i] > 8) {
                cnt += 1;
            } else {
                cnt -= 1;
            }

            // 第二步:查看前缀和数组中cnt值是否出现过。若没出现过,则设置cnt第一次出现的位置,
            // 并计算cnt第一次出现时,以cnt作为结尾且表现良好的区间长度的值f[cnt]
            if (idx.find(cnt) == idx.end()) {
                // 如果在idx中没有找到cnt对应的值,就设置cnt第一次出现的位置。
                idx[cnt] = i;

                // 第三步:计算cnt第一次出现时,以cnt作为结尾且表现良好的区间的长度。
                // 如果在cnt前面没有找到cnt-1的值出现的位置,则以cnt作为结尾且表现良好的区间的长度设置为0
                // 注:本题中前缀和数组是连续的,且相邻两个值相差为1,因而只需要在cnt的前面寻找比cnt小1的数。
                if (idx.find(cnt - 1) == idx.end()) {   // cnt前面没有比cnt小1的值,如图中没有比-2小1的值,因此以-2作为结尾且表现良好的区间的长度为0
                    f[cnt] = 0;
                } else {
                    // 在cnt前面出现了比cnt小1的值,则使用递推公式求以cnt作为结尾,且表现良好的区间的长度。
                    // 递推公式:f(n) = f(n-1) + p(n) - p(n-1),其中p(n)表示值n此刻出现的位置,p(n-1)表示值n-1第一次出现的位置。
                    f[cnt] = f[cnt - 1] + (i - idx[cnt - 1]);
                }
            }

            // 第四步:实时计算以 前缀和数组中的每个值作为结尾时,表现良好的区间的长度,并更新最长的长度。
            // 如果cnt在之前出现过,且比cnt小1的值也出现过,则可使用递推公式求此刻以cnt作为结尾且表现良好的区间的长度,并更新最长区间的长度。
            // 如果比cnt小1的值在前面没有出现过,则此刻以cnt作为结尾且表现良好的区间长度为0,则不用更新最长区间的长度。
            // 注意,不能使用answer = max(answer, f[cnt]); 因为f[cnt]表示cnt第一次出现时表现良好的区间的长度。而在前缀和数组中,cnt的值等于
            // 同一个值的情况可能在多个位置出现,因而在求表现良好的最长区间时,要时实计算以cnt作为结尾且表现良好的区间的长度。
            // 如图中1出现在了多个位置,而f[1]表示值1第一次出现时表现良好的区间长度。因此要重新计算f[cnt - 1] + i - ind[cnt - 1]的大小。
            if (idx.find(cnt - 1) != idx.end()) {
                int length = f[cnt - 1] + i - idx[cnt - 1];     // 实时计算此刻以cnt最为结尾时表现良好的区间的长度。
                answer = max(answer, length);
            }
        }
        return answer;
    }
};


int main() {
    vector<int> hours = {9,9,6,0,6,6,9};
    Solution *solution = new Solution();
    printf("%d\n", solution->longestWPI(hours));
    return 0;
}
  • Python代码
# -*- coding: utf-8 -*-

from typing import List


class Solution:
    def __init__(self):
        pass

    def longestWPI(self, hours: List[int]) -> int:
        idx = dict()    # 记录前缀和数组中每种值第一次出现的位置。
        fn = dict()     # 记录前缀和数组中,每个值n第一次出现时,以n作为结尾且表现良好的区间的长度。
        idx[0] = -1     # 前缀和数组的第一个元素为0,并将其下标为设置为-1。
        fn[0] = 0       # 初始化以前缀和数组的第一个元素0作为结尾,且表现良好的区间的长度为0
        sum = 0         # 用于计算前缀和数组中每个位置的值。
        answer = 0
        hours_len = len(hours)
        score = [0] * (hours_len + 1)  # 前缀和数组,前缀和数组的第一个元素要设置为0,因而数组的长度比hours的长度大1.

        # 第一步:计算前缀和数组中的每个值。
        for i in range(hours_len):
            sum += 1 if hours[i] > 8 else -1
            score[i + 1] = sum      # 因为前缀和数组的第一个元素必须为0,因此从第二个位置开始存放计算出来的值。

        # 第二步:遍历前缀和数组,查看前缀和数组中cnt值是否出现过。若没出现过则设置cnt第一次出现的位置。
        for i in range(hours_len):
            cnt = score[i + 1]
            # 若cnt没出现过,则设置cnt第一次出现的位置,并计算cnt第一次出现时,以cnt作为结尾且表现良好的区间长度的值f[cnt]
            if cnt not in idx.keys():
                idx[cnt] = i    # 如果在idx中没有找到cnt对应的值,就设置cnt第一次出现的位置。

                # 第三步:计算cnt第一次出现时,以cnt作为结尾且表现良好的区间的长度。
                # 如果在cnt前面没有找到cnt-1的值出现的位置,则以cnt作为结尾且表现良好的区间的长度设置为0
                # 注:本题中前缀和数组是连续的,且相邻两个值相差为1,因而只需要在cnt的前面寻找比cnt小1的数。
                if cnt - 1 not in idx.keys():
                    fn[cnt] = 0
                else:
                    # 在cnt前面出现了比cnt小1的值,则使用递推公式求以cnt作为结尾,且表现良好的区间的长度。
                    # 递推公式:f(n) = f(n-1) + p(n) - p(n-1),其中p(n)表示值n此刻出现的位置,p(n-1)表示值n-1第一次出现的位置。
                    fn[cnt] = fn[cnt - 1] + (i - idx[cnt - 1])

            # 第四步:实时计算以 前缀和数组中的每个值作为结尾时,表现良好的区间的长度,并更新最长的长度。
            # 如果cnt在之前出现过,且比cnt小1的值也出现过,则可使用递推公式求此刻以cnt作为结尾且表现良好的区间的长度,并更新最长区间的长度。
            # 如果比cnt小1的值在前面没有出现过,则此刻以cnt作为结尾且表现良好的区间长度为0,则不用更新最长区间的长度。
            # 注意,不能使用answer = max(answer, f[cnt]); 因为f[cnt]表示cnt第一次出现时表现良好的区间的长度。而在前缀和数组中,cnt的值等于
            # 同一个值的情况可能在多个位置出现,因而在求表现良好的最长区间时,要时实计算以cnt作为结尾且表现良好的区间的长度。
            # 如图中1出现在了多个位置,而f[1]表示值1第一次出现时表现良好的区间长度。因此要重新计算f[cnt - 1] + i - ind[cnt - 1]的大小。
            if cnt - 1 in idx.keys():
                length = fn[cnt - 1] + i - idx[cnt - 1] # 实时计算此刻以cnt最为结尾时表现良好的区间的长度。
                answer = max(answer, length)
        return answer


def main():
    solution = Solution()
    hours = [9, 9, 6, 0, 6, 6, 9]
    print(solution.longestWPI(hours))


if __name__ == "__main__":
    main()

说明

  • 对应LeetCode第1124题。
  • 链接:https://leetcode-cn.com/problems/longest-well-performing-interval/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpWebRequest 响应时间最长的原因可能有多个,以下是一些可能的原因: 1. 网络延迟:响应时间受到网络延迟的影响,如果网络连接不稳定或网络负载较高,会导致响应时间延长。 2. 服务器处理时间:服务器可能在处理请求时需要执行复杂的操作,比如查询大量数据或执行计算密集型任务,这些操作会增加响应时间。 3. 数据传输量:如果请求或响应中包含大量数据,会增加数据传输的时间,进而延长响应时间。 4. 服务器负载:如果服务器同时处理大量请求,会导致服务器负载过高,从而降低请求的处理速度,延长响应时间。 5. DNS 解析时间:在发送请求之前,需要将域名解析为 IP 地址,如果 DNS 解析时间较长,会增加整体响应时间。 6. 防火墙或代理设置:防火墙或代理服务器的设置可能会对请求和响应进行检查和过滤,这些额外的步骤会增加响应时间。 要减少 HttpWebRequest 响应时间最长的问题,可以尝试以下方法: - 优化网络连接:确保网络连接稳定,并尽量选择网络负载较低的时间段进行请求。 - 优化服务器端处理:减少不必要的计算和数据查询操作,尽量减少服务器端的响应时间。 - 减少数据传输量:如果可能,尽量减少请求和响应中的数据量。 - 考虑缓存:如果响应的数据是静态的或者可以被缓存的,可以考虑使用缓存来减少对服务器的请求。 - 使用 CDN:如果适用,可以考虑使用内容分发网络(CDN)来加速数据传输。 - 使用异步请求:通过使用异步请求,可以在等待服务器响应时执行其他操作,从而提高效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值