算法题(最长连续休息时间)

151 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

题目信息描述

一天可以被分为 nn 个时段。

一个工人的每日工作安排可以用一个长度为 nn 的 0101 序列 a1,a2,…,ana1,a2,…,an 来表示。

aiai 为 00 表示第 ii 个时间段是工作时间,aiai 为 11 表示第 ii 个时间段是休息时间。

工人日复一日的严格按照这个工作安排来进行工作和休息。

请问,工人的最长连续休息时间有多长(单位:时段)?

注意,连续休息时间可能跨天。

保证工人至少在一个时间段处于工作状态。

输入格式

第一行包含整数 TT,表示共有 TT 组测试数据。

每组数据第一行包含整数 nn。

第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an。

输出格式

每组数据输出一行结果,表示最长连续休息时间。

数据范围

1≤T≤101≤T≤10, 1≤n≤2×1051≤n≤2×105, 0≤ai≤10≤ai≤1, 同一测试点内所有 nn 的和不超过 2×1052×105。

输入样例:

4
5
1 0 1 0 1
6
0 1 0 1 1 0
7
1 0 1 1 1 0 1
3
0 0 0

输出样例:

2
2
3
0

思路

既然可以跨天,那就直接构造一个n*2的数组存两次,这道题就解出来了。或者可以这样理解这道题目,它其实就是环形区间找最长连续1的个数,只要断环为链即可。存数据,如果最后一个数据是1,就从后往前遍历获取可以连接的时间,然后把这个数值存入第一个时间,再从头开始找最大长度。

代码

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;
int T;
int f[200050];
int main()
{
    cin >> T;
    while(T -- ){
        int n;
        cin >> n;
        memset(f, 0, sizeof(f));
        for(int i = 0; i < n; ++i){
            cin >> f[i];
        }
        int count = 0;
        if(f[n - 1] == 1){
        for(int i = n - 1; ;--i ){
            int j = i - 1;
            while(f[j] == 1)j--;
            count = i - j;
            break;
        }
        }
        if(f[0])f[0] += count;
        int ans = 0;
        for(int i = 0; i < n; ++i){
            if(f[i] >= 1){
            int j = i + 1;
            while(f[j] == 1)j++;
            ans = max(ans,f[i] + j - i - 1);
            i = j;
        }
        }
        cout << ans << endl;
    }
    return 0;
}