OJ【最佳升级时间窗】

题目描述: 有一套系统需要升级,为了减小系统升级期间的影响,需根据系统过去几周内的平均每小时的访问数据,来预测最佳升级时间窗,时间窗的选择规则如下:

1、升级时间窗内累计用户访问量必须小于等于给定的容忍值
2、升级时间窗必须是连续的X个小时,越大越好,最大的X即为最佳升级时间窗,且不超过7*24
3、升级时间窗允许跨周期
现给定升级影响的容忍值,和一个周期(7*24)的每小时用户访问量的历史数据(整数数组),请计算最佳升级时间窗,并返回其开始时间和结束时间的下标,如果存在多个最佳升级时间窗时,返回开始时间下标最小的一个

输入:

第一行为整数n,表示给定的升级影响的容忍值,取值范围:[0,2^31)

第二行为724个整数,表示一个周期(724)的每个小时用户访问量,每个值的取值范围:[0,2^31)

输出:

两个整数,分别表示所计算出的最佳升级时间窗的开始时间下标(包含)和结束时间下标(包含),不存在时返回-1,-1

样例1:

6
1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 12 11 10 9 8 7 6 5 4 3 2 1

 输出:

 22 25

最佳升级窗口为:2 1 1 2

样例2:

167
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 167 1

输出:

 167 165

样例3:

200
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

输出: 

0 167

题解:

① C++滑动窗口:

思路:

        1、sum记录窗口内数据的和,当sum小于等于n时,窗口右边界向右移动;

        2、当sum大于n时,窗口左边界向左移动,且sum 需要减去左边界的值。

        3、满足要求的窗口被记录在ans数组中,且后面只记录笔前面出现窗口周期长的记录。

        4、当 sum小于n值,且 r - l 大于等于整个周期长度时,说明整个周期都满足升级要求。

        5、r取余是因为可以跨周期,如样例2.

#include <iostream>
#include <vector>

using namespace std;

const int ARR_LEN (7*24);

class Solution {
public:
    vector<int> getBestTime(int n, vector<int> arr) {
        int l = 0;
        int r = 0;
        int sum = arr[l];
        int maxLen = -1;
        vector<int> ans{-1,-1};
        int size = arr.size();
        for(; l < size; l++) {
            while(sum <= n) {
                if(r - l > maxLen) {
                    maxLen = r - l;
                    ans.push_back(l);
                    ans.push_back(r % size);
                }
                r++;
                sum += arr[r % size];
                if(r - l >= 168) {
                    sum -= arr[l];
                    break;
                }
            }
            sum -= arr[l];
        }
        return ans;
    }
};

int main()
{
    int count;
    cin >> count;
    vector<int> arr(ARR_LEN);
    for(int i = 0; i < ARR_LEN; i++) {
        cin >> arr[i];
    }

    Solution solu;
    vector<int> result = solu.getBestTime(count, arr);
    cout << result[result.size() - 2] << " "  << result[result.size() - 1] << endl;

}

② python 前缀和

        1、将数组复制一份至两倍长度

        2、求出新的数组的前缀和放到presum中

        3、presum[j] - presum[i] 则表示数组下标[i, j -1]窗口的和。如果和满足要求,则记录当前窗口下标,同时记录当前窗口长度

        4、对所有满足要求的窗口,以窗口长度为第一优先级,左下标为第二优先级排序。

        5、第一个数据则是最佳数据。

#!/usr/bin/env python
# coding=utf-8

class Solution :
    def get_best_time(self, n, arr):
        new_arr = arr * 2;
        windows = [];
        ans = []
        presum = [_ for _ in range(len(new_arr) + 1)]
        presum[0] = 0
        for i in range(1, len(new_arr) + 1):
            presum[i] = presum[i -1] + new_arr[ i - 1 ]
        for i in range(len(new_arr)):
            for j in range(i+1, len(new_arr) + 1):
                if presum[j] - presum[i] <= n:
                    windows.append([j-i, i, j -1])
                    if j - i >= 168:
                        return [i,j-1]
        if not windows:
            return [-1,-1]
        windows.sort(key = lambda x: (x[0], -x[1]), reverse = True);
        ans = [windows[0][1] % 168, windows[0][2] % 168]
        return ans


if __name__ == "__main__":
    n = int(input().strip())
    arr = list(map(int, input().strip().split()))

    function = Solution()
    result = function.get_best_time(n, arr);
    print(str.join(' ', map(str, result)))

  • 25
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值