华为OD机试真题——查找接口成功率最优时间段(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

在这里插入图片描述

2025 A卷 100分 题型

本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》

华为OD机试真题《查找接口成功率最优时间段》:


文章快捷目录

题目描述及说明

Java

python

JavaScript

C

GO

更多内容


题目名称:查找接口成功率最优时间段


知识点: 滑动窗口、前缀和、逻辑处理
时间限制: 1秒
空间限制: 256MB
限定语言: 不限


题目描述

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

输入描述

  • 第一行为minAverageLost
  • 第二行为数组,元素通过空格分隔。
  • minAverageLost及数组元素取值范围为0~100的整数,数组长度不超过100。

输出描述

  • 输出所有满足条件的最长时间段下标对,格式为{beginIndex}-{endIndex}(下标从0开始)。
  • 若存在多个相同长度的最优时间段,按起始下标从小到大排序,并用空格拼接。

用例

  1. 输入

    1  
    0 1 2 3 4  
    

    输出

    0-2  
    

    说明:前3个元素的平均值为1,满足条件。

  2. 输入

    2  
    0 0 100 2 2 99 0 2  
    

    输出

    0-1 3-4 6-7  
    

    说明:下标0-1、3-4、6-7对应的子数组平均值均≤2,且均为最长时段。


Java

问题分析

我们需要找到数组中所有满足平均失败率小于等于给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。

解题思路

  1. 转换数组:将每个元素减去给定的平均失败率,问题转化为寻找子数组的和小于等于0的最长长度。
  2. 前缀和数组:计算转换后数组的前缀和,便于快速计算子数组的和。
  3. 遍历所有可能的子数组:对于每个可能的结束下标,遍历所有可能的起始下标,记录满足条件的最长子数组。
  4. 收集结果:记录所有最长的子数组,按起始下标排序后输出。

代码实现

import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int minAverageLost = Integer.parseInt(scanner.nextLine());String[] parts = scanner.nextLine().split(" ");int[] nums = new int[parts.length];for (int i = 0; i < parts.length; i++) {nums[i] = Integer.parseInt(parts[i]);}// 转换为每个元素减去minAverageLost的数组int[] b = new int[nums.length];for (int i = 0; i < nums.length; i++) {b[i] = nums[i] - minAverageLost;}// 计算前缀和数组int[] prefixSum = new int[b.length + 1];for (int i = 0; i < b.length; i++) {prefixSum[i + 1] = prefixSum[i] + b[i];}int maxLen = 0;List<int[]> result = new ArrayList<>();// 遍历所有可能的结束下标jfor (int j = 0; j < b.length; j++) {// 遍历所有可能的起始下标ifor (int i = 0; i <= j; i++) {// 检查子数组i到j的和是否<=0if (prefixSum[j + 1] <= prefixSum[i]) {int currentLen = j - i + 1;if (currentLen > maxLen) {maxLen = currentLen;result.clear();result.add(new int[]{i, j});} else if (currentLen == maxLen) {result.add(new int[]{i, j});}}}}if (maxLen == 0) {System.out.println("NULL");return;}// 按起始下标排序Collections.sort(result, (a, bArr) -> {if (a[0] != bArr[0]) {return a[0] - bArr[0];} else {return a[1] - bArr[1];}});// 使用LinkedHashSet去重并保持顺序LinkedHashSet<String> seen = new LinkedHashSet<>();for (int[] interval : result) {seen.add(interval[0] + "-" + interval[1]);}// 输出结果System.out.println(String.join(" ", seen));}
}

代码详细解析

  1. 输入处理:读取输入的平均失败率和数组。
  2. 数组转换:将每个元素减去平均失败率,转换为新数组b
  3. 前缀和计算:构建前缀和数组prefixSum,用于快速计算子数组的和。
  4. 遍历子数组:双重循环遍历所有可能的起始和结束下标,检查子数组的和是否满足条件。
  5. 记录最长子数组:动态更新最长长度,并记录所有符合条件的子数组。
  6. 结果排序与去重:按起始下标排序,使用LinkedHashSet去重并保持顺序。
  7. 输出结果:拼接结果字符串并输出。

示例测试

示例1输入:
1  
0 1 2 3 4  

输出:

0-2
示例2输入:
2  
0 0 100 2 2 99 0 2  

输出:

0-1 3-4 6-7  
示例3输入:
3  
1 1 1  

输出:

0-2

综合分析

  1. 时间复杂度:O(n²),遍历所有可能的子数组,适用于数组长度较小的情况(n ≤ 100)。
  2. 空间复杂度:O(n),存储前缀和数组和结果列表。
  3. 优势:利用前缀和数组快速计算子数组的和,确保正确性和效率。
  4. 适用场景:适用于需要查找连续子数组满足特定条件的场景,如平均值、和等限制。

python

问题分析

我们需要找到数组中所有满足平均失败率 ≤ 给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。


解题思路

  1. 数学转换
    将问题转换为:寻找子数组的和 ≤ 0 的最长连续区间(原数组每个元素减去平均值后的新数组)。

  2. 前缀和数组
    计算新数组的前缀和,利用前缀和快速判断子数组的和是否 ≤ 0。

  3. 暴力遍历
    遍历所有可能的子数组,记录满足条件的最长区间。

  4. 结果处理
    去重并排序结果,按指定格式输出。


代码实现

def main():import sysinput = sys.stdin.read().splitlines()min_avg = int(input[0].strip())  # 读取容忍值arr = list(map(int, input[1].strip().split()))  # 读取失败率数组# 转换为差值数组(元素 - 容忍值)diff = [num - min_avg for num in arr]n = len(diff)# 计算前缀和数组(多一位方便计算)prefix = [0] * (n + 1)for i in range(n):prefix[i+1] = prefix[i] + diff[i]max_len = 0result = []# 遍历所有可能的子数组for end in range(n):for start in range(end + 1):# 子数组和是否 <= 0(prefix[end+1] <= prefix[start])if prefix[end+1] <= prefix[start]:current_len = end - start + 1if current_len > max_len:max_len = current_lenresult = [(start, end)]elif current_len == max_len:result.append((start, end))if max_len == 0:print("NULL")return# 去重并排序(起始下标升序)unique = sorted(list(set(result)), key=lambda x: (x[0], x[1]))# 格式化输出output = ' '.join([f"{s}-{e}" for s, e in unique])print(output)if __name__ == "__main__":main()

代码详细解析

1. 输入处理
min_avg = int(input[0].strip())  # 读取容忍值
arr = list(map(int, input[1].strip().split()))  # 读取失败率数组
  • 第一行为容忍值 min_avg
  • 第二行为空格分隔的失败率数组。
2. 数学转换
diff = [num - min_avg for num in arr]
  • 将每个元素减去容忍值,转换为新数组 diff。问题转化为:寻找 diff 中子数组和 ≤ 0 的最长区间。
3. 前缀和计算
prefix = [0] * (n + 1)
for i in range(n):prefix[i+1] = prefix[i] + diff[i]
  • 构建前缀和数组 prefix,其中 prefix[i] 表示原数组前 i 个元素的和。
  • 例如:diff[1..3] 的和 = prefix[4] - prefix[1]
4. 暴力遍历所有子数组
for end in range(n):for start in range(end + 1):if prefix[end+1] <= prefix[start]:current_len = end - start + 1if current_len > max_len:max_len = current_lenresult = [(start, end)]elif current_len == max_len:result.append((start, end))
  • 外层循环遍历子数组的结束下标 end
  • 内层循环遍历子数组的起始下标 start
  • 通过前缀和判断 diff[start..end] 的和是否 ≤ 0。
  • 动态更新最长长度和结果列表。
5. 结果处理
unique = sorted(list(set(result)), key=lambda x: (x[0], x[1]))
output = ' '.join([f"{s}-{e}" for s, e in unique])
  • 使用 set 去重重复的区间。
  • 按起始下标升序、结束下标升序排序。
  • 格式化为 0-2 形式拼接输出。

示例测试

示例1输入:
1  
0 1 2 3 4

输出:

0-2

解析:
子数组 [0,1,2] 的平均值为 1,满足条件,长度为3,是唯一最长。

示例2输入:
2  
0 0 100 2 2 99 0 2

输出:

0-1 3-4 6-7

解析:

  • 0-1 平均值 0
  • 3-4 平均值 2
  • 6-7 平均值 1
    均为长度2的最长区间。
示例3输入:
3  
1 1 1

输出:

NULL

解析:
所有子数组的平均值均为 1,无法满足容忍值 3


综合分析

  1. 时间复杂度O(n²)

    • 双重循环遍历所有可能的子数组,适用于 n ≤ 100 的题目限制。
  2. 空间复杂度O(n)

    • 存储前缀和数组和结果列表,空间与数组长度成线性关系。
  3. 优势

    • 避免浮点运算:通过前缀和与差值数组,用整数运算判断条件。
    • 代码简洁:利用Python的列表推导和排序函数简化逻辑。
  4. 适用场景

    • 需要查找满足条件的连续子数组,且输入规模较小的场景。

JavaScript

问题分析

我们需要找到数组中所有满足平均失败率 ≤ 给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。


解题思路

  1. 数学转换:将每个元素减去容忍值,问题转化为寻找子数组的和 ≤ 0 的最长区间。
  2. 前缀和数组:计算转换后的数组的前缀和,快速判断子数组的和是否满足条件。
  3. 暴力遍历:遍历所有可能的子数组,记录满足条件的最长区间。
  4. 结果处理:按起始下标排序后输出。

代码实现

const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout,terminal: false
});let lines = [];
rl.on('line', (line) => {lines.push(line.trim());
});rl.on('close', () => {const minAverageLost = parseInt(lines[0]);const arr = lines[1].split(' ').map(Number);const n = arr.length;// 转换为差值数组(元素 - 容忍值)const diff = arr.map(num => num - minAverageLost);// 计算前缀和数组const prefixSum = [0];for (let i = 0; i < n; i++) {prefixSum.push(prefixSum[i] + diff[i]);}let maxLen = 0;const result = [];// 遍历所有可能的子数组for (let end = 0; end < n; end++) {for (let start = 0; start <= end; start++) {const sum = prefixSum[end + 1] - prefixSum[start];if (sum <= 0) {const currentLen = end - start + 1;if (currentLen > maxLen) {maxLen = currentLen;result.length = 0; // 清空旧结果result.push([start, end]);} else if (currentLen === maxLen) {result.push([start, end]);}}}}if (maxLen === 0) {console.log('NULL');return;}// 按起始下标排序result.sort((a, b) => a[0] - b[0] || a[1] - b[1]);// 转换为字符串输出const output = result.map(pair => `${pair[0]}-${pair[1]}`).join(' ');console.log(output);
});

代码详细解析

  1. 输入处理

    • readline 逐行读取输入,存入 lines 数组。
    • minAverageLost 读取为整数,arr 读取为整数数组。
  2. 数学转换

    const diff = arr.map(num => num - minAverageLost);
    
    • 将每个元素减去容忍值,转换为差值数组。
  3. 前缀和计算

    const prefixSum = [0];
    for (let i = 0; i < n; i++) {prefixSum.push(prefixSum[i] + diff[i]);
    }
    
    • 构建前缀和数组 prefixSum,用于快速计算子数组的和。
  4. 暴力遍历子数组

    for (let end = 0; end < n; end++) {for (let start = 0; start <= end; start++) {const sum = prefixSum[end + 1] - prefixSum[start];if (sum <= 0) {const currentLen = end - start + 1;// 更新最长结果}}
    }
    
    • 双重循环遍历所有子数组,计算子数组的和是否 ≤ 0。
    • 动态更新最长长度和结果数组。
  5. 结果处理

    result.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
    const output = result.map(pair => `${pair[0]}-${pair[1]}`).join(' ');
    
    • 按起始下标排序,转换为字符串格式输出。

示例测试

示例1输入:
1  
0 1 2 3 4  

输出

0-2  
示例2输入:
2  
0 0 100 2 2 99 0 2  

输出

0-1 3-4 6-7  
示例3输入:
3  
1 1 1  

输出

NULL  

综合分析

  1. 时间复杂度O(n²)

    • 双重循环遍历所有子数组,适用于输入规模较小(数组长度 ≤ 100)的场景。
  2. 空间复杂度O(n)

    • 存储前缀和数组和结果数组,空间与输入规模成线性关系。
  3. 优势

    • 避免浮点运算:通过差值数组和前缀和,用整数运算快速判断条件。
    • 严格顺序处理:确保结果按起始下标排序。
  4. 适用场景

    • 需要快速处理连续子数组的平均值问题的场景。

C++

问题分析

我们需要找到数组中所有满足平均失败率 ≤ 给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。


解题思路

  1. 数学转换
    将问题转换为:寻找子数组的和 ≤ 0 的最长连续区间(原数组每个元素减去平均值后的新数组)。

  2. 前缀和数组
    计算新数组的前缀和,利用前缀和快速判断子数组的和是否 ≤ 0。

  3. 暴力遍历
    遍历所有可能的子数组,记录满足条件的最长区间。

  4. 结果处理
    去重并排序结果,按指定格式输出。


代码实现

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <set>using namespace std;int main() {// 读取输入int minAverageLost;cin >> minAverageLost;cin.ignore(); // 忽略换行符string line;getline(cin, line);    // 读取数组行istringstream iss(line);vector<int> nums;int num;while (iss >> num) {   // 解析数组元素nums.push_back(num);}int n = nums.size();if (n == 0) {          // 处理空数组cout << "NULL" << endl;return 0;}// 转换为差值数组(元素 - 容忍值)vector<int> diff(n);for (int i = 0; i < n; ++i) {diff[i] = nums[i] - minAverageLost;}// 计算前缀和数组vector<long long> prefixSum(n + 1, 0);for (int i = 0; i < n; ++i) {prefixSum[i + 1] = prefixSum[i] + diff[i];}int maxLen = 0;vector<pair<int, int>> result; // 存储所有满足条件的区间// 遍历所有可能的子数组for (int end = 0; end < n; ++end) {for (int start = 0; start <= end; ++start) {// 检查子数组的和是否 <= 0if (prefixSum[end + 1] <= prefixSum[start]) {int currentLen = end - start + 1;if (currentLen > maxLen) {maxLen = currentLen;result.clear();       // 清空旧结果result.emplace_back(start, end);} else if (currentLen == maxLen) {result.emplace_back(start, end);}}}}if (maxLen == 0) { // 没有满足条件的区间cout << "NULL" << endl;return 0;}// 按起始下标排序,若起始相同则按结束下标排序sort(result.begin(), result.end(), [](const auto& a, const auto& b) {if (a.first != b.first) return a.first < b.first;return a.second < b.second;});// 去重(可能因不同路径产生相同区间)set<pair<int, int>> uniqueSet(result.begin(), result.end());result.assign(uniqueSet.begin(), uniqueSet.end());// 格式化输出bool first = true;for (const auto& [s, e] : result) {if (!first) cout << " ";cout << s << "-" << e;first = false;}cout << endl;return 0;
}

代码详细解析

1. 输入处理
int minAverageLost;
cin >> minAverageLost;
cin.ignore(); // 忽略换行符
string line;
getline(cin, line); // 读取数组行
istringstream iss(line);
  • 读取容忍值 minAverageLost
  • 读取数组行并使用 istringstream 分割元素。
2. 转换为差值数组
vector<int> diff(n);
for (int i = 0; i < n; ++i) {diff[i] = nums[i] - minAverageLost;
}
  • 将每个元素减去容忍值,生成新数组 diff。问题转化为:寻找 diff 中子数组和 ≤ 0 的最长区间。
3. 前缀和数组计算
vector<long long> prefixSum(n + 1, 0);
for (int i = 0; i < n; ++i) {prefixSum[i + 1] = prefixSum[i] + diff[i];
}
  • 构建前缀和数组 prefixSum,其中 prefixSum[i] 表示前 i 个元素的和。
  • 例如:diff[1..3] 的和 = prefixSum[4] - prefixSum[1]
4. 遍历所有子数组
for (int end = 0; end < n; ++end) {for (int start = 0; start <= end; ++start) {if (prefixSum[end + 1] <= prefixSum[start]) {// 更新结果}}
}
  • 外层循环遍历子数组的结束下标 end
  • 内层循环遍历起始下标 start
  • 通过前缀和判断子数组的和是否 ≤ 0。
5. 动态更新结果
if (currentLen > maxLen) {maxLen = currentLen;result.clear();result.emplace_back(start, end);
} else if (currentLen == maxLen) {result.emplace_back(start, end);
}
  • 发现更长的子数组时清空旧结果,保存新区间。
  • 遇到等长子数组时追加结果。
6. 排序与去重
sort(result.begin(), result.end(), [](const auto& a, const auto& b) {if (a.first != b.first) return a.first < b.first;return a.second < b.second;
});
set<pair<int, int>> uniqueSet(result.begin(), result.end());
  • 按起始下标升序、结束下标升序排序。
  • 使用 set 去重,确保结果唯一。
7. 格式化输出
for (const auto& [s, e] : result) {if (!first) cout << " ";cout << s << "-" << e;first = false;
}
  • 将结果转换为 0-2 格式输出,用空格分隔。

示例测试

示例1输入:
1  
0 1 2 3 4  

输出:

0-2  
示例2输入:
2  
0 0 100 2 2 99 0 2  

输出:

0-1 3-4 6-7  
示例3输入:
3  
1 1 1  

输出:

NULL  

综合分析

  1. 时间复杂度O(n²)

    • 双重循环遍历所有子数组,适用于数组长度较小(n ≤ 100)的场景。
  2. 空间复杂度O(n²)

    • 最坏情况下存储所有可能的子数组区间(例如所有元素相同)。
  3. 优势

    • 避免浮点运算:通过整数运算快速判断条件。
    • 严格排序与去重:确保结果符合题目要求。
  4. 适用场景

    • 需要快速处理连续子数组的平均值问题,且输入规模较小的场景。

C

问题分析

我们需要找到数组中所有满足平均失败率 ≤ 给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。


解题思路

  1. 数学转换
    将每个元素减去容忍值,问题转化为寻找子数组的和 ≤ 0 的最长连续区间。

  2. 前缀和数组
    计算转换后的数组的前缀和,利用前缀和快速判断子数组的和是否满足条件。

  3. 暴力遍历
    遍历所有可能的子数组,记录满足条件的最长区间。

  4. 结果处理
    去重并排序结果,按指定格式输出。


代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {int start;int end;
} Interval;int compare_intervals(const void *a, const void *b) {Interval *ia = (Interval *)a;Interval *ib = (Interval *)b;if (ia->start != ib->start) return ia->start - ib->start;return ia->end - ib->end;
}int main() {int minAverageLost;char line[1000];// 读取容忍值fgets(line, sizeof(line), stdin);minAverageLost = atoi(line);// 读取数组行fgets(line, sizeof(line), stdin);int nums[100], n = 0;char *token = strtok(line, " ");while (token != NULL && n < 100) {nums[n++] = atoi(token);token = strtok(NULL, " ");}if (n == 0) {printf("NULL\n");return 0;}// 转换为差值数组(元素 - 容忍值)int diff[100];for (int i = 0; i < n; i++) {diff[i] = nums[i] - minAverageLost;}// 计算前缀和数组long long prefixSum[101] = {0};for (int i = 0; i < n; i++) {prefixSum[i + 1] = prefixSum[i] + diff[i];}// 收集所有满足条件的区间Interval *intervals = NULL;int interval_count = 0, interval_capacity = 0;int max_len = 0;for (int end = 0; end < n; end++) {for (int start = 0; start <= end; start++) {if (prefixSum[end + 1] <= prefixSum[start]) {// 记录区间if (interval_count >= interval_capacity) {interval_capacity = (interval_capacity == 0) ? 1 : interval_capacity * 2;intervals = realloc(intervals, interval_capacity * sizeof(Interval));}intervals[interval_count].start = start;intervals[interval_count].end = end;interval_count++;// 更新最大长度int current_len = end - start + 1;if (current_len > max_len) max_len = current_len;}}}if (max_len == 0) {printf("NULL\n");free(intervals);return 0;}// 筛选出最长区间Interval *result = NULL;int result_count = 0, result_capacity = 0;for (int i = 0; i < interval_count; i++) {int len = intervals[i].end - intervals[i].start + 1;if (len == max_len) {if (result_count >= result_capacity) {result_capacity = (result_capacity == 0) ? 1 : result_capacity * 2;result = realloc(result, result_capacity * sizeof(Interval));}result[result_count++] = intervals[i];}}free(intervals);// 排序和去重qsort(result, result_count, sizeof(Interval), compare_intervals);int unique_count = 0;for (int i = 0; i < result_count; i++) {if (i == 0 || (result[i].start != result[i-1].start || result[i].end != result[i-1].end)) {result[unique_count++] = result[i];}}// 输出结果if (unique_count == 0) {printf("NULL\n");} else {for (int i = 0; i < unique_count; i++) {printf("%d-%d", result[i].start, result[i].end);if (i != unique_count - 1) printf(" ");}printf("\n");}free(result);return 0;
}

代码详细解析

  1. 输入处理

    • 使用 fgets 读取输入行,strtok 分割字符串并转换为整数数组。
  2. 数学转换

    int diff[100];
    for (int i = 0; i < n; i++) {diff[i] = nums[i] - minAverageLost;
    }
    
    • 将每个元素减去容忍值,生成新数组 diff
  3. 前缀和计算

    long long prefixSum[101] = {0};
    for (int i = 0; i < n; i++) {prefixSum[i + 1] = prefixSum[i] + diff[i];
    }
    
    • 构建前缀和数组 prefixSum,用于快速计算子数组的和。
  4. 遍历子数组

    for (int end = 0; end < n; end++) {for (int start = 0; start <= end; start++) {if (prefixSum[end + 1] <= prefixSum[start]) {// 记录区间}}
    }
    
    • 双重循环遍历所有子数组,判断其和是否 ≤ 0。
  5. 动态数组管理

    • 使用 realloc 动态扩展数组 intervalsresult,存储区间数据。
  6. 筛选最长区间

    • 遍历所有区间,筛选出长度等于 max_len 的区间。
  7. 排序与去重

    qsort(result, result_count, sizeof(Interval), compare_intervals);
    for (int i = 0; i < result_count; i++) {if (i == 0 || (result[i].start != result[i-1].start || result[i].end != result[i-1].end)) {result[unique_count++] = result[i];}
    }
    
    • 按起始下标排序,遍历去重相邻重复项。
  8. 输出结果

    • 按格式输出所有唯一的最长区间。

示例测试

示例1输入:
1  
0 1 2 3 4  

输出

0-2  
示例2输入:
2  
0 0 100 2 2 99 0 2  

输出

0-1 3-4 6-7  
示例3输入:
3  
1 1 1  

输出

NULL  

综合分析

  1. 时间复杂度O(n²)

    • 双重循环遍历所有子数组,适用于数组长度较小(n ≤ 100)的场景。
  2. 空间复杂度O(n²)

    • 最坏情况下存储所有可能的子数组区间。
  3. 优势

    • 避免浮点运算:通过整数运算快速判断条件。
    • 严格排序与去重:确保结果符合题目要求。
  4. 适用场景

    • 需要快速处理连续子数组的平均值问题,且输入规模较小的场景。

GO

问题分析

我们需要找到数组中所有满足平均失败率 ≤ 给定值的最长连续子数组,并输出这些子数组的起始和结束下标。如果有多个相同长度的子数组,按起始下标升序排列。


解题思路

  1. 数学转换
    将每个元素减去容忍值,问题转化为寻找子数组的和 ≤ 0 的最长连续区间。

  2. 前缀和数组
    计算转换后的数组的前缀和,快速判断子数组的和是否满足条件。

  3. 暴力遍历
    遍历所有可能的子数组,记录满足条件的最长区间。

  4. 结果处理
    筛选最长区间,排序并去重后输出。


代码实现

package mainimport ("bufio""fmt""os""sort""strconv""strings"
)type Interval struct {start, end int
}func main() {scanner := bufio.NewScanner(os.Stdin)// 读取输入参数scanner.Scan()minAverageLost, _ := strconv.Atoi(scanner.Text())scanner.Scan()numsLine := scanner.Text()numsStr := strings.Fields(numsLine)nums := make([]int, len(numsStr))for i, s := range numsStr {nums[i], _ = strconv.Atoi(s)}// 转换数组为差值数组(元素 - 容忍值)diff := make([]int, len(nums))for i, num := range nums {diff[i] = num - minAverageLost}// 计算前缀和数组prefix := make([]int, len(diff)+1)prefix[0] = 0for i := 0; i < len(diff); i++ {prefix[i+1] = prefix[i] + diff[i]}// 收集所有满足条件的区间var allIntervals []Intervalfor end := 0; end < len(diff); end++ {for start := 0; start <= end; start++ {if prefix[end+1] <= prefix[start] {allIntervals = append(allIntervals, Interval{start, end})}}}if len(allIntervals) == 0 {fmt.Println("NULL")return}// 找到最大长度maxLen := 0for _, interval := range allIntervals {length := interval.end - interval.start + 1if length > maxLen {maxLen = length}}// 筛选出最长区间的候选var candidates []Intervalfor _, interval := range allIntervals {if interval.end-interval.start+1 == maxLen {candidates = append(candidates, interval)}}// 排序候选区间(按起始下标升序,结束下标升序)sort.Slice(candidates, func(i, j int) bool {if candidates[i].start != candidates[j].start {return candidates[i].start < candidates[j].start}return candidates[i].end < candidates[j].end})// 去重(跳过相邻重复项)var results []Intervalfor i, interval := range candidates {if i == 0 || (interval.start != candidates[i-1].start || interval.end != candidates[i-1].end) {results = append(results, interval)}}// 输出结果if len(results) == 0 {fmt.Println("NULL")} else {output := make([]string, len(results))for i, interval := range results {output[i] = fmt.Sprintf("%d-%d", interval.start, interval.end)}fmt.Println(strings.Join(output, " "))}
}

代码详细解析

  1. 输入处理

    • 使用 bufio.Scanner 读取输入,转换第一行为 minAverageLost,第二行为整数数组。
  2. 数学转换

    diff := make([]int, len(nums))
    for i, num := range nums {diff[i] = num - minAverageLost
    }
    
    • 将每个元素减去容忍值,生成新数组 diff。问题转化为:寻找 diff 中和 ≤ 0 的子数组。
  3. 前缀和计算

    prefix := make([]int, len(diff)+1)
    for i := 0; i < len(diff); i++ {prefix[i+1] = prefix[i] + diff[i]
    }
    
    • 构建前缀和数组 prefixprefix[i] 表示前 i 个元素的和。
  4. 收集所有符合条件的区间

    for end := 0; end < len(diff); end++ {for start := 0; start <= end; start++ {if prefix[end+1] <= prefix[start] {allIntervals = append(allIntervals, Interval{start, end})}}
    }
    
    • 双重循环遍历所有子数组,判断其和是否 ≤ 0,记录符合条件的区间。
  5. 筛选最长区间

    • 遍历 allIntervals 找到最大长度 maxLen
    • 筛选出所有长度为 maxLen 的区间存入 candidates
  6. 排序与去重

    sort.Slice(candidates, ...) // 按起始下标升序排序
    for i, interval := range candidates {if i == 0 || ... { // 去重相邻重复项results = append(results, interval)}
    }
    
    • 排序后遍历跳过重复项,确保结果唯一。
  7. 输出结果

    • 将结果格式化为字符串并输出,若无有效结果输出 NULL

示例测试

示例1输入:
1  
0 1 2 3 4  

输出:

0-2  
示例2输入:
2  
0 0 100 2 2 99 0 2  

输出:

0-1 3-4 6-7  
示例3输入:
3  
1 1 1  

输出:

NULL  

综合分析

  1. 时间复杂度O(n²)

    • 双重循环遍历所有子数组,适用于数组长度较小(n ≤ 100)的场景。
  2. 空间复杂度O(n²)

    • 最坏情况下存储所有可能的子数组区间(如所有元素相同)。
  3. 优势

    • 避免浮点运算:通过整数运算快速判断条件。
    • 严格顺序处理:确保结果按起始下标排序。
  4. 适用场景

    • 需要快速处理连续子数组的平均值问题,且输入规模较小的场景。

更多内容:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】,关注我,获取更多实用教程/资源!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/78275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为OD机试真题——绘图机器(2025A卷:100分)Java/python/JavaScript/C++/C/GO最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 本文收录于专栏&#xff1a;《2025华为OD真题目录全流程解析/备考攻略/经验…

基于 Python(selenium) 的百度新闻定向爬虫:根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容

该项目能够根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容。 一、项目准备 1. 开发环境配置 操作系统:支持 Windows、macOS、Linux 等主流操作系统,本文以 Windows 为例进行说明。Python 版本:建议使用 Python 3.8 及以上版本,以确保代码的兼容性和性能。…

MySQL表的操作 -- 表的增删改查

目录 1. 表的创建2. 表的查看3. 表的修改4. 表的删除5. 总结 1. 表的创建 1.查看字符集及效验规则 2. 表的创建 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;创建用户表1 创建用…

如何解决极狐GitLab 合并冲突?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 合并冲突 (BASIC ALL) 合并冲突发生在合并请求的两个分支&#xff08;源分支和目标分支&#xff09;对相同代码行进行了不同…

oracle不同数据库版本的自增序列

-- 查看数据库版本 SELECT * FROM v$version WHERE banner LIKE Oracle%; 1. Oracle 12c及以上版本支持 id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) PRIMARY KEY, -- 语法 id NUMBER GENER…

VIC-3D非接触全场应变测量系统用于小尺寸测量之电子元器件篇—研索仪器DIC数字图像相关技术

在5G通信、新能源汽车电子、高密度集成电路快速迭代的今天&#xff0c;电子元件的尺寸及连接工艺已进入亚毫米级竞争阶段&#xff0c;这种小尺寸下的力学性能评估对测量方式的精度有更高的要求&#xff0c;但传统应变测量手段常因空间尺寸限制及分辨率不足难以捕捉真实形变场。…

pod 创建私有库指南

步骤 参考&#xff1a;iOS Pod 私有库创建指南-百度开发者中心 下面主要是对参考链接里面的解释&#xff1a; 创建两个仓库&#xff1a; 一个叫podframe.git&#xff0c;用来存放自定义的framework&#xff0c;比如TestPodFrame.framework一个叫podspec.git&#xff0c;用来…

【JavaEE】Spring AOP的注解实现

目录 一、AOP 与 Spring AOP二、Spring AOP简单实现三、详解Spring AOP3.1 Spring AOP 核心概念3.1.1 切点&#xff08;Pointcut&#xff09;3.1.2 连接点&#xff08;Join Point&#xff09;3.1.3 通知&#xff08;Advice&#xff09;3.1.4 切面&#xff08;Aspect&#xff09…

协作开发攻略:Git全面使用指南 — 结语

协作开发攻略&#xff1a;Git全面使用指南 — 结语 Git 是一种分布式版本控制系统&#xff0c;用于跟踪文件和目录的变更。它能帮助开发者有效管理代码版本&#xff0c;支持多人协作开发&#xff0c;方便代码合并与冲突解决&#xff0c;广泛应用于软件开发领域。 文中内容仅限技…

如何用AI主动突出画面主体!涂鸦新方案助剪辑、工业巡检、医疗影像等领域,实现自动追踪+智能放大

随着智能 IPC 设备&#xff08;如安防摄像头、宠物陪伴机器人、婴儿监视器等&#xff09;日益普及&#xff0c;越来越多的生活场景被实时记录。然而在实际使用中&#xff0c;由于设备安装位置不当、广角镜头视野过大等原因&#xff0c;经常会出现拍摄主体占比过小的问题&#x…

数据湖DataLake和传统数据仓库Datawarehouse的主要区别是什么?优缺点是什么?

数据湖和传统数据仓库的主要区别 以下是数据湖和传统数据仓库的主要区别&#xff0c;以表格形式展示&#xff1a; 特性数据湖传统数据仓库数据类型支持结构化、半结构化及非结构化数据主要处理结构化数据架构设计扁平化架构&#xff0c;所有数据存储在一个大的“池”中多层架…

当智驾成标配,车企暗战升级|2025上海车展

文&#xff5c;刘俊宏 编&#xff5c;王一粟 智能化无处不在的2025年上海车展&#xff0c;回归了卖车的初衷。 光锥智能在展会暴走两天&#xff0c;最大的感触是今年的车展少了争奇斗艳&#xff0c;多了些许务实。 回顾智能汽车时代的三场重要车展。2023年的上海车展充满了…

如何在Spring Boot中禁用Actuator端点安全性

在 Spring Boot 应用中&#xff0c;Spring Boot Actuator 提供了一系列用于监控和管理应用的端点&#xff08;如 /actuator/health、/actuator/metrics&#xff09;&#xff0c;这些端点默认可能受到 Spring Security 的保护&#xff0c;要求身份验证或授权。然而&#xff0c;在…

【mongodb】系统保留的数据库名

目录 1. admin2. config3. local4. test&#xff08;非严格保留&#xff0c;但常作为默认测试数据库&#xff09;5. 注意事项6. 其他相关说明 1. admin 1.用途&#xff1a;用于存储数据库的权限和用户管理相关数据。2.特点&#xff1a;该数据库是 MongoDB 的超级用户数据库&am…

Redis是单线程的,如何提高多核CPU的利用率?

一句话回答&#xff1a; Redis 是单线程处理客户端命令&#xff0c;但可以通过 多实例部署、I/O 多路复用、后台线程 Redis 6 的 I/O Thread 支持&#xff0c;来充分利用多核 CPU。 一、Redis 单线程 ≠ 整个 Redis 都是单线程&#xff01; Redis 主要的 网络事件 命令执行 …

关于mysql的事务和索引

1. 事务四大特性&#xff08;ACID&#xff09; 原子性&#xff1a;事务的操作要么全部成功&#xff0c;要么全部失败回滚&#xff0c;不可分割。 一致性&#xff1a;事务执行前后&#xff0c;数据必须满足业务规则&#xff08;如账户总额不变&#xff09;。 隔离性&#xff1…

【Python】保持Selenium稳定爬取的方法(防检测策略)

selenium 防检测策略的方法汇总&#xff1a; 合理设置延迟&#xff1a;请求间添加随机延迟 (2-10秒) 限制爬取频率&#xff1a;控制每小时/每天的请求量 轮换用户代理&#xff1a;准备至少10个不同的User-Agent 使用住宅代理&#xff1a;优先选择高质量的住宅代理IP 处理验…

SpringSecurity源码解读AbstractAuthenticationProcessingFilter

一、介绍 AbstractAuthenticationProcessingFilter 是 Spring Security 框架里的一个抽象过滤器,它在处理基于表单的认证等认证流程时起着关键作用。它继承自 GenericFilterBean,并实现了 javax.servlet.Filter 接口。此过滤器的主要功能是拦截客户端发送的认证请求,对请求…

什么是DDD?为什么它正在取代传统架构?

什么是DDD&#xff1f;为什么它正在取代传统架构&#xff1f; 1. 传统开发模式的痛点 在经典的MVC架构中&#xff0c;开发流程往往从数据库表结构设计开始&#xff0c;业务逻辑散落在Service层&#xff0c;随着需求迭代容易形成「大泥球」代码&#xff1a; 实体类变成纯粹的…

基于外部中中断机制,实现以下功能: 1.按键1,按下和释放后,点亮LED 2.按键2,按下和释放后,熄灭LED 3.按键3,按下和释放后,使得LED闪烁

题目&#xff1a; 参照外部中断的原理和代码示例,再结合之前已经实现的按键切换LED状态的实验&#xff0c;用外部中断改进其实现。 请自行参考文档《中断》当中&#xff0c;有关按键切换LED状态的内容, 自行连接电路图&#xff0c;基于外部中断机制&#xff0c;实现以下功能&am…