【华为OD】2024D卷——查找接口成功率最优时间段

题目描述:
服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值,
数组中的数值为0~100的整数,给定一个数值(minAverageLost)表示某个时间段内平均失败率容忍值,即平均失败率小于等于minAverageLost,
找出数组中最长时间段,如果未找到则直接返回NULL。

输入描述:
输入有两行内容,
第一行为{minAverageLost),
第二行为(数组),
数组元索通过空格(“ ”)分隔,
minAverageLost及数组中元素取值范围为0~100的整数,数组元素的个数不会超过100个。

输出描述:
找出平均值小于等于minAverageLost的最长时间段,输出数组下标对,格式[beginlndex}-{endlndx}(下标从0开始),
如果同时存在多个最长时间段,则输出多个下标对且下标对之间使用空格(“ ”)拼接,多个下标对按下标从小到大排序。

示例1



输入:
1
0 1 2 3 4
输出:
0-2

说明:
A、输入解释:minAverageLost=1,数组[0,1.2.3.4]
B、前3个元素的平均值为1,因此数组第一个至第三个数组下标,即0-2

解题思路:

1、处理输入

2、滑动窗口:

        start、end均从0开始新建窗口,

        对应窗口值average = sum(list[start:end + 1]) / end -start + 1;

        当窗口值 > minAverageLost时,缩小窗口,得到满足条件的最大窗口(子数组)长度

3、处理输出:

        使用字典存储符合条件的子数组(start, end)、 子数组长度;

        获取最大子数组长度,格式化输出对应start ,end


代码部分

def minAverageArray(minAverageLost, losts):
    start = 0       #窗口开始位置
    length_lost = len(losts)
    sub_sn = {}     #字典存储所有小于minAverageLost的位置(start,end)元组与长度

    # 求子数组平均值
    def aver(lists, start, end, length):
        if end - start + 1 == 1:
            return lists[start]
        else:
            return sum(lists[start:end + 1]) / length

    for end in range(length_lost):
        tmp_len = end - start + 1       #窗口大小
        # tmp_aver = sum(losts[start:end]) / tmp_len     #窗口值
        while aver(losts, start, end, tmp_len) > minAverageLost:       #当窗口值大于容忍值时,减小窗口
            if tmp_len == 1:
                break
            start += 1      #减小窗口
            tmp_len = end - start + 1  # 窗口大小
        #存储所有窗口值 小于 忍耐值的 窗口
        sub_sn[(start, end)] = tmp_len

    # 求最大窗口值(符合条件的最长数组长度)
    length_sub = max(sub_sn.values())
    # 排序后,字典对象转变为列表对象
    sort_sub_sn = sorted(sub_sn.items(), key=lambda x: (-x[1], x[0][0]))
    # 存储最大的位置序列
    sub_list = []
    for x in sort_sub_sn:
        if x[1] == length_sub:
            s = '{}-{}'.format(x[0][0], x[0][1])
            sub_list.append(s)
    return sub_list

if __name__ =='__main__':
    minAverageLost = int(input())
    losts = list(map(int, input().split()))
    result_list = minAverageArray(minAverageLost, losts)
    print(' '.join(result_list))

其他思路:

        可以将滑动窗口的窗口值设为sum[start: end + 1];

        找到满足窗口(子数组)长度 *  minAverageLost  < sumsum[start: end + 1]时,缩小窗口


代码部分

def minAverageArray_I(failure_rates, min_average_lost):
    n = len(failure_rates)
    if n == 0:
        return None
        # 存储满足条件的时间段的下标对
    results = []
    # 窗口的左边界和右边界
    left = 0
    sum_failure = 0
    max_length = 0

    for right in range(n):
        # 将当前失败率加入到窗口内总和
        sum_failure += failure_rates[right]
        # 当窗口内平均失败率大于容忍值时,尝试缩小窗口
        while (right - left + 1) * min_average_lost < sum_failure:
            sum_failure -= failure_rates[left]
            left += 1
            # 如果当前窗口满足条件,并且比之前的更长,则更新结果
        if (right - left + 1) > max_length:
            max_length = right - left + 1
            results = [f"{left}-{right}"]  # 重置结果列表,因为可能存在多个等长最优解,但这里只保留最新一个
        elif (right - left + 1) == max_length:
            results.append(f"{left}-{right}")  # 长度相同,添加新解

    return " ".join(results) if results else None

知识点:滑动窗口、列表


结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值