题目描述: 服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值, 数组中的数值为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
知识点:滑动窗口、列表
结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路