华为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
- 限定语言:不限
题目描述
用数组代表每个人的能力,一个比赛活动要求参赛团队的最低能力值为N。每个团队可以由1人或2人组成,且1个人只能参加1个团队。请计算出最多可以派出多少支符合要求的团队?
输入描述:
- 第一行为总人数,范围[1,500000]。
- 第二行为每个人的能力值数组,元素取值范围[1,500000],数组大小与总人数一致。
- 第三行为团队要求的最低能力值N,范围[1,500000]。
输出描述:
- 最多可以派出的团队数量。
示例:
输入:
5
3 1 5 7 9
8
输出:
3
说明:
- 3和5组成一队(3+5≥8),1和7组成一队(1+7≥8),9单独一队(9≥8),共3队。
Java
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int total = scanner.nextInt();int[] abilities = new int[total];for (int i = 0; i < total; i++) {abilities[i] = scanner.nextInt();}int N = scanner.nextInt();Arrays.sort(abilities); // 将能力值排序,便于双指针操作int left = 0; // 左指针,指向当前最小未处理的能力值int right = total - 1; // 右指针,指向当前最大未处理的能力值int count = 0; // 统计符合要求的团队数量while (left <= right) { // 当还有人未处理时循环if (abilities[right] >= N) { // 右指针的人能力值达标,单独成队count++;right--; // 处理下一个更大的能力值(指针左移)} else { // 右指针的人无法单独成队,尝试与左指针的人组队if (left < right && abilities[left] + abilities[right] >= N) { // 左右指针不同且组合达标count++;left++; // 左指针右移,处理下一个更小的能力值right--; // 右指针左移,处理下一个更大的能力值} else { // 无法组队,左指针右移(当前右指针的人无法配对,只能放弃)left++;}}}System.out.println(count);}
}
代码详解
- 输入处理:读取总人数、能力数组和最低要求N。
- 排序:将数组排序,便于双指针从两端向中间处理。
- 双指针初始化:
left
指向最小元素,right
指向最大元素。 - 循环处理:
- 右指针单独成队:若当前右指针的人能力≥N,直接成队。
- 尝试组队:若左右指针非同一人且能力之和≥N,组队。
- 无法处理:左指针右移,放弃当前右指针的人。
- 输出结果:统计所有可能的队伍数量。
示例测试
-
示例输入1:
5 3 1 5 7 9 8
输出:3
说明:3和5组队,1和7组队,9单独成队。 -
示例输入2:
2 4 5 8
输出:1
说明:4和5组队。 -
示例输入3:
3 3 3 3 5
输出:1
说明:其中两人组队(3+3≥5),剩下一人无法成队。
综合分析
- 时间复杂度:O(n log n),排序耗时O(n log n),双指针遍历O(n)。
- 空间复杂度:O(1),仅使用常量额外空间。
- 正确性:
- 贪心策略确保每次尽可能组成最多的队伍。
- 排序和双指针处理所有可能的组合。
- 适用性:
- 处理大规模数据高效(如50万人)。
- 逻辑清晰,避免复杂递归或动态规划。
- 为何最优:
- 贪心策略优先处理能力大的人,最大化利用高能力值。
- 双指针保证线性时间复杂度,避免重复计算。
python
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
def max_teams():import sys# 读取输入数据total = int(sys.stdin.readline()) # 总人数abilities = list(map(int, sys.stdin.readline().split())) # 能力数组N = int(sys.stdin.readline()) # 团队最低能力要求# 将能力数组从小到大排序(排序后:左指针指向最小,右指针指向最大)abilities.sort()left = 0 # 左指针初始指向最小值right = total - 1 # 右指针初始指向最大值count = 0 # 统计符合要求的团队数量# 双指针贪心算法while left <= right:# 如果当前右指针的人能力值 >= N,单独成队if abilities[right] >= N:count += 1right -= 1 # 处理下一个更大的能力值(右指针左移)else:# 尝试与左指针的人组队if left < right and (abilities[left] + abilities[right] >= N):count += 1left += 1 # 左指针右移(处理更小的能力值)right -= 1 # 右指针左移(处理更大的能力值)else:# 无法组队,丢弃当前左指针的人(因为它无法与任何更大的值组队)left += 1print(count)# 示例测试
if __name__ == "__main__":# 示例1:输入5\n3 1 5 7 9\n8 → 输出3# 示例2:输入2\n4 5\n8 → 输出1# 示例3:输入3\n3 3 3\n5 → 输出1max_teams()
代码详解
-
输入处理:
total = int(sys.stdin.readline()) # 读取总人数 abilities = list(map(int, sys.stdin.readline().split())) # 读取能力数组 N = int(sys.stdin.readline()) # 读取最低要求N
- 使用
sys.stdin.readline()
逐行读取输入,避免缓冲区问题。
- 使用
-
排序能力数组:
abilities.sort() # 排序后数组顺序为从小到大
- 排序后左指针指向最小值,右指针指向最大值。
-
双指针初始化:
left = 0 # 指向最小值的索引 right = total - 1 # 指向最大值的索引 count = 0 # 统计结果
- 左指针从最小能力开始,右指针从最大能力开始。
-
双指针贪心算法:
while left <= right:if abilities[right] >= N: # 右指针的人单独成队count += 1right -= 1else:if left < right and (abilities[left] + abilities[right] >= N):count += 1left += 1right -= 1else:left += 1
- 右指针单独成队:如果当前最大值满足要求,直接计数。
- 组队尝试:若左右指针非同一人且能力之和达标,组队并移动双指针。
- 无法组队:左指针右移(放弃当前左值,因为它无法与更大的值组队)。
-
输出结果:
print(count)
示例测试
-
示例1输入:
5 3 1 5 7 9 8
处理过程:
- 排序后数组:
[1, 3, 5, 7, 9]
- 右指针指向9(≥8)→ 单独成队,
count=1
,右指针→7 - 右指针7不达标,尝试与左指针1组队(1+7=8)→ 成队,
count=2
,左右指针→3和5 - 右指针5不达标,尝试与左指针3组队(3+5=8)→ 成队,
count=3
输出:3
- 排序后数组:
-
示例2输入:
2 4 5 8
处理过程:
- 排序后数组:
[4, 5]
- 右指针5不达标,尝试与左指针4组队(4+5=9≥8)→ 成队,
count=1
输出:1
- 排序后数组:
-
示例3输入:
3 3 3 3 5
处理过程:
- 排序后数组:
[3, 3, 3]
- 右指针3不达标,尝试与左指针3组队(3+3=6≥5)→ 成队,
count=1
- 剩余右指针3不达标,无法组队
输出:1
- 排序后数组:
综合分析
-
时间复杂度:O(n log n)
- 排序时间复杂度为O(n log n),双指针遍历O(n)。
-
空间复杂度:O(n)
- 存储能力数组需要O(n)空间。
-
正确性:
- 贪心策略确保每次优先用最小的代价(最小左值)满足组队条件。
- 双指针从两端向中间逼近,覆盖所有可能的组队情况。
-
适用性:
- 能处理最大50万的数据规模,满足题目要求。
-
为什么这是最佳实现?
- 贪心选择最优:总让剩余的最大值优先被使用,最大化后续组队可能性。
- 双指针高效:线性遍历,避免暴力枚举所有组合(O(n²))。
- 代码简洁:逻辑清晰,无冗余操作。
JavaScript
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
function maxTeams(abilities, N) {// 将能力数组从小到大排序(确保数值正确排序)abilities.sort((a, b) => a - b);let left = 0; // 左指针,指向最小能力值的索引let right = abilities.length - 1; // 右指针,指向最大能力值的索引let count = 0; // 统计符合要求的团队数量// 双指针贪心算法while (left <= right) {// 如果当前右指针的人能力值 >= N,单独成队if (abilities[right] >= N) {count++;right--; // 处理下一个更大的能力值(右指针左移)} else {// 尝试与左指针的人组队if (left < right && abilities[left] + abilities[right] >= N) {count++;left++; // 左指针右移(处理更小的能力值)right--; // 右指针左移(处理更大的能力值)} else {// 无法组队,丢弃当前左指针的人(因为它无法与任何更大的值组队)left++;}}}return count;
}// 示例测试
console.log(maxTeams([3, 1, 5, 7, 9], 8)); // 输出3
console.log(maxTeams([4, 5], 8)); // 输出1
console.log(maxTeams([3, 3, 3], 5)); // 输出1
代码详解
-
排序能力数组:
abilities.sort((a, b) => a - b); // 从小到大排序
- JavaScript 的
sort
默认按字符串排序,需传入比较函数确保数值正确排序。
- JavaScript 的
-
双指针初始化:
let left = 0; // 左指针初始指向最小值的索引 let right = abilities.length - 1; // 右指针初始指向最大值的索引
left
从数组头部开始,right
从尾部开始。
-
循环处理双指针:
while (left <= right) {// 右指针的人能力值达标,单独成队if (abilities[right] >= N) {count++;right--;} else {// 尝试与左指针的人组队if (left < right && abilities[left] + abilities[right] >= N) {count++;left++;right--;} else {left++; // 无法组队,左指针右移}} }
- 右指针单独成队:若当前最大值满足要求,直接计数。
- 组队尝试:若左右指针非同一人且能力之和达标,则组队。
- 无法组队:左指针右移(放弃当前左值,尝试更小的左值)。
-
返回结果:
return count;
示例测试
-
示例1:
[3, 1, 5, 7, 9]
,N=8
- 排序后:
[1, 3, 5, 7, 9]
9
单独成队 →count=1
7
与1
组队 →count=2
5
与3
组队 →count=3
输出:3
- 排序后:
-
示例2:
[4, 5]
,N=8
- 排序后:
[4, 5]
5
与4
组队 →count=1
输出:1
- 排序后:
-
示例3:
[3, 3, 3]
,N=5
- 排序后:
[3, 3, 3]
- 两个
3
组队 →count=1
输出:1
- 排序后:
综合分析
-
时间复杂度:O(n log n)
- 排序耗时
O(n log n)
,双指针遍历O(n)
,总复杂度由排序主导。
- 排序耗时
-
空间复杂度:O(1)
- 仅使用常数级变量(
left
、right
、count
)。
- 仅使用常数级变量(
-
正确性:
- 贪心策略正确性:每次优先处理最大值,确保后续可能的组队机会最大化。
- 双指针覆盖所有情况:从两端向中间逼近,确保所有可能组合被检查。
-
适用性:
- 处理大规模数据:50万级别的数据可在1秒内完成(排序+遍历)。
- 逻辑清晰:代码简洁,无复杂递归或动态规划。
-
为什么这是最佳实现?
- 贪心最优性:每次选择当前最优解(最大能力优先使用)。
- 高效性:双指针线性遍历,避免暴力枚举所有组合(复杂度从O(n²)降到O(n))。
- 低空间开销:无需额外存储空间,仅需基本变量。
C++
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
#include <iostream>
#include <vector>
#include <algorithm> // 用于排序using namespace std;int maxTeams(vector<int>& abilities, int N) {sort(abilities.begin(), abilities.end()); // 将能力值从小到大排序int left = 0; // 左指针,指向最小能力值的索引int right = abilities.size() - 1; // 右指针,指向最大能力值的索引int count = 0; // 统计符合要求的团队数量// 双指针贪心算法while (left <= right) {// 如果当前右指针的人能力值 >= N,单独成队if (abilities[right] >= N) {count++;right--; // 处理下一个更大的能力值(右指针左移)} else {// 尝试与左指针的人组队if (left < right && (abilities[left] + abilities[right] >= N)) {count++;left++; // 左指针右移(处理更小的能力值)right--; // 右指针左移(处理更大的能力值)} else {// 无法组队,丢弃当前左指针的人(因为它无法与任何更大的值组队)left++;}}}return count;
}int main() {// 示例测试vector<int> example1 = {3, 1, 5, 7, 9};cout << maxTeams(example1, 8) << endl; // 输出3vector<int> example2 = {4, 5};cout << maxTeams(example2, 8) << endl; // 输出1vector<int> example3 = {3, 3, 3};cout << maxTeams(example3, 5) << endl; // 输出1return 0;
}
代码详解
-
输入排序:
sort(abilities.begin(), abilities.end()); // 将能力值从小到大排序
- 排序后左指针指向最小值,右指针指向最大值,便于后续双指针操作。
-
双指针初始化:
int left = 0; // 左指针初始指向最小值 int right = abilities.size() - 1; // 右指针初始指向最大值
left
从数组头部开始,right
从尾部开始。
-
循环处理双指针:
while (left <= right) {if (abilities[right] >= N) { // 右指针的人能力值达标,单独成队count++;right--;} else {if (left < right && (abilities[left] + abilities[right] >= N)) {count++;left++; // 左指针右移(处理更小的能力值)right--; // 右指针左移(处理更大的能力值)} else {left++; // 无法组队,左指针右移}} }
- 右指针单独成队:若当前最大值满足要求,直接计数。
- 组队尝试:若左右指针非同一人且能力之和达标,则组队。
- 无法组队:左指针右移(放弃当前左值,尝试更小的左值)。
-
返回结果:
return count; // 返回总团队数
示例测试
-
示例1输入:
{3, 1, 5, 7, 9}, N=8
- 排序后数组:
[1, 3, 5, 7, 9]
9
单独成队 →count=1
7
与1
组队 →count=2
5
与3
组队 →count=3
输出:3
- 排序后数组:
-
示例2输入:
{4, 5}, N=8
- 排序后数组:
[4, 5]
5
与4
组队 →count=1
输出:1
- 排序后数组:
-
示例3输入:
{3, 3, 3}, N=5
- 排序后数组:
[3, 3, 3]
- 两个
3
组队 →count=1
输出:1
- 排序后数组:
综合分析
-
时间复杂度:O(n log n)
- 排序时间复杂度为
O(n log n)
,双指针遍历O(n)
,总复杂度由排序主导。
- 排序时间复杂度为
-
空间复杂度:O(1)
- 仅使用常数级变量(
left
、right
、count
),无额外空间开销。
- 仅使用常数级变量(
-
正确性:
- 贪心策略正确性:优先处理最大值,确保后续可能的组队机会最大化。
- 双指针覆盖所有情况:从两端向中间逼近,确保所有可能组合被检查。
-
适用性:
- 处理大规模数据:50万级别的数据可在1秒内完成(排序+遍历)。
- 逻辑清晰:代码简洁,无复杂递归或动态规划。
-
为什么这是最佳实现?
- 贪心最优性:每次选择当前最优解(最大能力优先使用)。
- 高效性:双指针线性遍历,避免暴力枚举所有组合(复杂度从O(n²)降到O(n))。
- 低空间开销:无需额外存储空间,仅需基本变量。
C
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
#include <stdio.h>
#include <stdlib.h>// 比较函数用于升序排序
int compare(const void *a, const void *b) {return (*(int *)a - *(int *)b);
}int max_teams(int *abilities, int size, int N) {qsort(abilities, size, sizeof(int), compare); // 将能力值从小到大排序int left = 0; // 左指针,指向最小能力值的索引int right = size - 1; // 右指针,指向最大能力值的索引int count = 0; // 统计符合要求的团队数量// 双指针贪心算法while (left <= right) {// 如果当前右指针的人能力值 >= N,单独成队if (abilities[right] >= N) {count++;right--;} else {// 尝试与左指针的人组队if (left < right && (abilities[left] + abilities[right] >= N)) {count++;left++;right--;} else {// 无法组队,左指针右移left++;}}}return count;
}int main() {int total, N;scanf("%d", &total); // 读取总人数// 动态分配数组内存int *abilities = (int *)malloc(total * sizeof(int));for (int i = 0; i < total; i++) {scanf("%d", &abilities[i]); // 读取能力数组}scanf("%d", &N); // 读取最低要求Nprintf("%d\n", max_teams(abilities, total, N));free(abilities); // 释放动态分配的内存return 0;
}
代码详解
-
比较函数:
int compare(const void *a, const void *b) {return (*(int *)a - *(int *)b); // 升序排序 }
- 用于
qsort
的排序函数,确保能力值从小到大排列。
- 用于
-
排序与双指针初始化:
qsort(abilities, size, sizeof(int), compare); int left = 0, right = size - 1, count = 0;
qsort
对数组排序,双指针初始化指向数组两端。
-
双指针处理逻辑:
while (left <= right) {if (abilities[right] >= N) { // 右指针单独成队count++;right--;} else {if (left < right && (abilities[left] + abilities[right] >= N)) { // 组队count++;left++;right--;} else { // 无法组队,左移left++;}} }
- 右指针单独成队:若当前最大值满足要求,直接计数。
- 组队尝试:若左右指针非同一人且能力之和达标,则组队。
- 无法组队:左指针右移(放弃当前左值)。
-
输入处理与内存管理:
int *abilities = (int *)malloc(total * sizeof(int)); // 动态分配数组 free(abilities); // 释放内存
- 动态分配数组内存避免栈溢出,使用后释放内存防止泄漏。
示例测试
-
输入1:
5 3 1 5 7 9 8
排序后数组:
[1, 3, 5, 7, 9]
处理过程:9
单独成队 →count=1
7
和1
组队 →count=2
5
和3
组队 →count=3
输出:3
-
输入2:
2 4 5 8
排序后数组:
[4, 5]
处理过程:5
和4
组队 →count=1
输出:1
-
输入3:
3 3 3 3 5
排序后数组:
[3, 3, 3]
处理过程:- 两个
3
组队 →count=1
输出:1
- 两个
综合分析
-
时间复杂度:O(n log n)
qsort
排序时间复杂度为 O(n log n),双指针遍历 O(n),总复杂度由排序主导。
-
空间复杂度:O(1)
- 除输入数组外,仅使用常数级变量(
left
、right
、count
)。
- 除输入数组外,仅使用常数级变量(
-
正确性:
- 贪心策略:优先处理最大值,确保后续可能的组队机会最大化。
- 双指针覆盖所有情况:从两端向中间逼近,确保所有可能组合被检查。
-
适用性:
- 处理大规模数据:50万级别的数据可在1秒内完成排序和遍历。
- 内存安全:动态分配内存避免栈溢出,释放防止内存泄漏。
-
为什么这是最佳实现?
- 贪心最优性:每次选择当前最优解(最大能力优先使用)。
- 高效性:双指针线性遍历,避免暴力枚举所有组合(复杂度从 O(n²) 降到 O(n))。
- 低空间开销:无需额外存储空间,仅需基本变量。
GO
问题分析
我们需要从一组人中选出尽可能多的团队,每个团队可以由1人或2人组成,且能力值之和需达到最低要求N。目标是找到最大的团队数量。
解题思路
- 排序数组:将能力值从小到大排序,便于双指针操作。
- 贪心策略:使用双指针,优先让能力大的人单独成队,若不能则尝试与能力小的人组队。
- 双指针操作:
- 右指针从最大能力开始,若单独满足要求则成队。
- 否则尝试与左指针的人组队,若满足则成队,否则左移找更小能力的人。
代码实现
package mainimport ("bufio""fmt""os""sort""strconv""strings"
)func maxTeams(abilities []int, N int) int {// 将能力数组从小到大排序sort.Ints(abilities)left := 0 // 左指针,指向最小能力值的索引right := len(abilities) - 1 // 右指针,指向最大能力值的索引count := 0 // 统计符合要求的团队数量// 双指针贪心算法for left <= right {if abilities[right] >= N { // 右指针的人能力值达标,单独成队count++right-- // 处理下一个更大的能力值(右指针左移)} else {// 尝试与左指针的人组队if left < right && (abilities[left]+abilities[right] >= N) {count++left++ // 左指针右移(处理更小的能力值)right-- // 右指针左移(处理更大的能力值)} else {// 无法组队,左指针右移(丢弃当前左指针的人)left++}}}return count
}func main() {// 读取输入scanner := bufio.NewScanner(os.Stdin)scanner.Scan()total, _ := strconv.Atoi(scanner.Text()) // 总人数scanner.Scan()// 读取能力数组字符串并转换为整数切片abilityStrs := strings.Fields(scanner.Text())abilities := make([]int, total)for i, s := range abilityStrs {abilities[i], _ = strconv.Atoi(s)}scanner.Scan()N, _ := strconv.Atoi(scanner.Text()) // 团队最低能力要求fmt.Println(maxTeams(abilities, N))
}
代码详解
-
输入处理:
scanner := bufio.NewScanner(os.Stdin) scanner.Scan() total, _ := strconv.Atoi(scanner.Text()) // 读取总人数
- 使用
bufio.Scanner
逐行读取输入,确保处理大输入时的高效性。
- 使用
-
能力数组转换:
abilityStrs := strings.Fields(scanner.Text()) // 分割字符串为切片 abilities := make([]int, total) for i, s := range abilityStrs {abilities[i], _ = strconv.Atoi(s) }
- 将输入的第二行(能力值字符串)分割并转换为整数切片。
-
排序与双指针初始化:
sort.Ints(abilities) // 对能力数组升序排序 left := 0 right := len(abilities) - 1
- 排序后左指针指向最小值,右指针指向最大值。
-
双指针处理逻辑:
if abilities[right] >= N { // 右指针单独成队count++right-- } else {if left < right && (abilities[left]+abilities[right] >= N) { // 组队count++left++right--} else { // 无法组队left++} }
- 右指针单独成队:若当前最大值满足要求,直接计数。
- 组队尝试:若左右指针非同一人且能力之和达标,则组队。
- 无法组队:左指针右移(放弃当前左值)。
-
输出结果:
fmt.Println(maxTeams(abilities, N))
示例测试
-
示例1输入:
5 3 1 5 7 9 8
处理过程:
- 排序后数组:
[1 3 5 7 9]
9
单独成队 →count=1
7
和1
组队 →count=2
5
和3
组队 →count=3
输出:3
- 排序后数组:
-
示例2输入:
2 4 5 8
处理过程:
- 排序后数组:
[4 5]
5
和4
组队 →count=1
输出:1
- 排序后数组:
-
示例3输入:
3 3 3 3 5
处理过程:
- 排序后数组:
[3 3 3]
- 两个
3
组队 →count=1
输出:1
- 排序后数组:
综合分析
-
时间复杂度:O(n log n)
sort.Ints
排序时间复杂度为 O(n log n),双指针遍历 O(n)。
-
空间复杂度:O(n)
- 存储能力数组需要 O(n) 空间。
-
正确性:
- 贪心策略正确性:每次优先处理最大值,确保后续可能的组队机会最大化。
- 双指针覆盖所有情况:从两端向中间逼近,确保所有可能组合被检查。
-
适用性:
- 处理大规模数据:50万级别的数据可在1秒内完成排序和遍历。
- 内存高效:切片动态分配内存,避免浪费。
-
为什么这是最佳实现?
- 贪心最优性:每次选择当前最优解(最大能力优先使用)。
- 高效性:双指针线性遍历,避免暴力枚举所有组合(复杂度从 O(n²) 降到 O(n))。
- 代码简洁:利用Go语言的内置排序和切片特性,逻辑清晰。
更多内容:
https://www.kdocs.cn/l/cvk0eoGYucWA
本文发表于【纪元A梦】,关注我,获取更多实用教程/资源!
相关文章:
华为OD机试真题——求最多可以派出多少支队伍(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录…...
《七年一剑》速读笔记
文章目录 书籍信息概览知己知彼市场的本质认识自我了解他人人剑合一 技术分析精要K线分型均线节奏形态画线成交量周期级别指标之王——MACD波动理论 管窥基本面A股周期论实战角度看财报 构建交易系统打开交易之门交易基础之买卖依据风险控制与仓位管理系统评估及情绪管理 实战秘…...
VMware-centOS7安装redis分布式集群
1.部署redis包 1.1 在usr/local文件夹里创建文件夹 mkdir software 1.2 进入文件夹 cd /usr/local/software/ 下载redis wget http://download.redis.io/releases/redis-6.2.6.tar.gz解压 tar zxvf redis-6.2.6.tar.gz重命名文件夹 mv redis-6.2.6 redis安装gcc编译器 yum i…...
Kubernetes(k8s)学习笔记(六)--KubeSphere前置环境安装
1、安装 helm(master 节点执行) Helm 是 Kubernetes 的包管理器。包管理器类似于我们在 Ubuntu 中使用的apt、Centos 中使用的 yum 或者 Python 中的 pip 一样,能快速查找、下载和安装软件包。Helm由客户端组件 helm 和服务端组件 Tiller 组…...
黑马点评day01(基于Redis)
1.7 Redis代替session的业务流程 1.7.1、设计key的结构 首先我们要思考一下利用redis来存储数据,那么到底使用哪种结构呢?由于存入的数据比较简单,我们可以考虑使用String,或者是使用哈希,如下图,如果使用…...
14.Excel:排序和筛选
一 位置 两个位置。 二 排序:如何使用 1.常规使用 补充:不弹出排序提醒排序。 选中要排序列中的任意一个单元格,然后排序。 2.根据要求进行排序 1.根据姓名笔画进行降序排序 要勾选上数据包含标题,默认是勾选了。 2.根据运营部、…...
力扣-字符串-468 检查ip
思路 考察字符串的使用,还有对所有边界条件的检查 spilt(“\.”),toCharArray,Integer.parseInt() 代码 class Solution {boolean checkIpv4Segment(String str){if(str.length() 0 || str.length() > 4) retur…...
C++名称空间
名称空间 名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。因此,在默认情况下,在名称空间中声明的名称的链接性为外部的(除非它引用了常量) 名称空间是开放的,你可以在…...
Redis 过期与淘汰机制全解析
概述 Redis 作为一种高性能的内存数据库,提供了数据过期和淘汰策略以管理存储的数据。本文将详细探讨 Redis 中数据失效的基本原理、实现方式,并结合源码进行分析,帮助读者更深入地理解和优化 Redis 的使用。 数据过期机制 过期键的存储方…...
PMP-第四章 项目整合管理(一)
项目整合管理 项目整合管理包括对项目管理过程组内的各种过程和项目管理活动而进行识别、定义、组合、统一与协调的各种过程和活动项目整合管理必须由项目经理负责。其他知识领域可以由相关领域专家管理,但整合的责任不能被授权或转移项目与项目管理本质上具有整合…...
VSCode搭建STM32开发调试环境
闲言碎语: 好久没更,在忙着科研→校招→写毕业论文。 临近毕业,总结自己的大学生活:C\C、Java、Python、深度学习,学的乱七八糟。 秋招找了个嵌入式工作(涉及AI应用),大致确定了以后…...
【数据结构】稀疏矩阵的快速转置
稀疏矩阵的快速转置 如图给出一个稀疏矩阵,要求表示出它的转置矩阵 由这个矩阵我们能轻松得到它的三元组顺序表 6行(x坐标)7列(y坐标)8个元素121213931-3361443245218611564-7 接下来我们同样把转置后的矩阵的三元组…...
【Godot】使用 Shader 实现可调节的精确切角效果
今天我们要实现的是一个四角精确切割Shader,可以在UI元素或Sprite的四个角分别切割出不同大小的三角形区域。 文章目录 什么是Godot Shader?数学原理详解左上角切割右上角切割右下角切割左下角切割四角切割Shader完整代码使用方法在Godot编辑器中设置通过代码控制进阶技巧1. …...
在CentOS环境中安装MySQL数据库保姆级教程
一.确认当前系统版本 1.1登录系统,切换至root账户 如图所示: 1.2:在终端中执行如下命令查看系统版本 cat /etc/redhat-release 二.添加 MySQL Yum 源 2.1访问MySQL开发者专区 https://dev.mysql.com/downloads/repo/yum/ TIPS: 1.发布包命…...
分布式系统中的 ActiveMQ:异步解耦与流量削峰(二)
四、流量削峰 (一)流量削峰原理深入解析 在当今互联网应用中,高并发场景屡见不鲜 。例如,电商平台的促销活动、在线票务系统的抢票时刻以及社交平台的热点事件爆发期等,都会在短时间内迎来大量用户请求。这些瞬间涌入…...
JAVA设计模式——(十)抽象工厂模式(Abstract Factory Pattern)
JAVA设计模式——(十)抽象工厂模式(Abstract Factory Pattern) 介绍理解实现工厂接口工厂实现类应用类应用类实现测试改造工厂类 应用 介绍 抽象工厂模式在工厂模式的基础上,适配的对象变为一组相关的对象,…...
STM32的定时器
定时器的介绍 介绍:STM32F103C8T6微控制器内部集成了多种类型的定时器,这些定时器在嵌入式系统中扮演着重要角色,用于计时、延时、事件触发以及PWM波形生成、脉冲捕获等应用。 *几种定时器(STM32F103系列)࿱…...
ubuntu-PyQt5安装+PyCharm配置QtDesigner + QtUIC
个人环境 ubuntu22.04 pycharm 2024.3 python 3.10 1)先使用apt命令在线安装 1)sudo apt install pyqt5* 2)sudo apt install qttools5-dev-tools2)Pycharm配置Pycharm External Tool 在设置—工具——外部工具中 配置QtDesigner Name :QtDesigne…...
测试基础笔记第十九天
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、接口的概念二、接口的类型三、接口测试1.概念2.原理:3.特点:4.实现方式:5.什么是自动化接口测试? 二、HTTP协议1.HTTP协议简介2.URL格式…...
Ubuntu 系统上广受好评的浏览器推荐
日常使用与开发者首选 Firefox 特点:开源、隐私保护强大,支持丰富扩展(如开发者工具、广告拦截),默认预装且跨平台兼容368。 适用场景:日常浏览、开发者调试(支持实时 CSS/JS 编辑)、…...
第 13 届蓝桥杯 C++ 青少组省赛中 / 高级组真题解析
一、选择题 第 1 题 题目:下列关于类中声明的变量描述正确的是 ( )。 选项: A. 只属于该类 B. 属于全局变量 C. 任何情况下都可被该类所有实例共享 D. 属于该类,某些情况下也可被该类不同实例所共享 答案:D 解析&…...
Win10下安装Linux-Ubuntu24.04双系统
0 引言 Ubuntu 24.04 LTS(代号“Noble Numbat”)是 Canonical 于 2024 年 4 月 25 日发布的第 10 个长期支持版本,专注于性能优化、企业安全和开发者体验提升 Windows 10 是微软于 2015 年 7 月发布的跨平台操作系统,融合了传统桌…...
express 怎么搭建 WebSocket 服务器
一:使用 express-ws var express require(express); var app express(); var expressWs require(express-ws)(app);app.use(function (req, res, next) {console.log(middleware);req.testing testing;return next(); });app.get(/, function(req, res, next){…...
模型部署——cuda编程入门
CUDA中的线程与线程束 kernel是在device上线程中并行执行的函数,核函数用__global__符号声明,在调用时需要用<<<grid_size, block_size>>>来指定kernel要执行的线程数量。在CUDA中,每一个线程都要执行核函数,并…...
llfc项目TCP服务器笔记
ChatServer 一个TCP服务器必然会有连接的接收,维持,收发数据等逻辑。那我们就要基于asio完成这个服务的搭建。主服务是这个样子的 #include "LogicSystem.h"#include <csignal>#include <thread>#include <mutex>#include "AsioIOServiceP…...
NPP库中libnppi模块介绍
1. libnppi 模块简介 libnppi 是 NPP 库中专门用于 图像处理 的模块,提供高度优化的 GPU 加速函数,支持: 图像滤波(卷积、形态学操作) 几何变换(旋转、缩放、透视变换) 颜色空间转换…...
从头训练小模型: 3 传统RLHF与DPO的区别
这个步骤我其实是忽略了。如果我的目标是建立一个安全领域的模型,我个人理解这步骤并不太必要。关于人类偏好对齐:在前面的训练步骤中,模型已经具备了基本的对话能力。 此时模型还不知道什么是好的回答,什么是不好的回答。我们希…...
Python-Django系列—视图
一、通用显示视图 以下两个基于类的通用视图旨在显示数据。在许多项目中,它们通常是最常用的视图。 1、DetailView class django.views.generic.detail.DetailView 当该视图执行时,self.object 将包含该视图正在操作的对象。 祖先(MRO&a…...
el-input Vue 3 focus聚焦
https://andi.cn/page/622173.html...
动态规划(5)路径问题--剑指offer -珠宝的最大值
题目: 现有一个记作二维矩阵 frame 的珠宝架,其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为: 只能从架子的左上角开始拿珠宝每次可以移动到右侧或下侧的相邻位置到达珠宝架子的右下角时,停止拿取 注意࿱…...
ZArchiver正版:高效文件管理,完美解压体验
在使用安卓设备的过程中,文件管理和压缩文件的处理是许多用户常见的需求。无论是解压下载的文件、管理手机存储中的文件,还是进行日常的文件操作,一款功能强大且操作简便的文件管理工具都能极大地提升用户体验。今天,我们要介绍的…...
Netlink在SONiC中的应用
Netlink在SONiC中的应用 Netlink介绍 Netlink 是 Linux 内核态程序与用户空间程序之间进行通信的机制之一,原本是用于传递网络协议栈中的各种控制消息。它采用和套接字(socket)编程接口相同的形式,常用于配置内核网络子系统&…...
ReentrantLock实现公平锁和非公平锁
在 Java 里,公平锁和非公平锁是多线程编程中用于同步的两种锁机制,它们的主要差异在于获取锁的顺序规则。下面是对二者的详细介绍: 公平锁 公平锁遵循 “先来先服务” 原则,也就是线程获取锁的顺序和请求锁的顺序一致。先请求锁…...
【C++】 —— 笔试刷题day_25
一、笨小猴 题目解析 这道题,给定一个字符str,让我们找到这个字符串中出现次数最多字母的出现次数maxn和出现次数最少字母的出现次数minn; 然后判断maxn - minn是否是一个质数,如果是就输出Lucky Word和maxn - minn;如…...
terraform resource创建了5台阿里云ecs,如要使用terraform删除其中一台主机,如何删除?
在 Terraform 中删除阿里云 5 台 ECS 实例中的某一台,具体操作取决于你创建资源时使用的 多实例管理方式(count 或 for_each)。以下是详细解决方案: 方法一:使用 for_each(推荐) 如果创建时使…...
Office 三大组件Excel、Word、Access 里 VBA 区别对比
以下是Excel、Word和Access在VBA中的主要区别对比及详细说明: 核心对象模型 Excel Workbook(工作簿)→ Worksheet(工作表)→ Range(单元格区域) 核心围绕单元格数据处理,如 Cells(1,1).Value = "数据" Word Document(文档)→ Range(文本范围)→ Paragrap…...
Linux 进程基础(二):操作系统
目录 一、什么是操作系统:用户和电脑之间的「翻译官」🌐 OS 的层状结构🧩 案例解析:双击鼠标的「跨层之旅」 二、操作系统的必要性探究:缺乏操作系统的环境面临的挑战剖析🔑 OS 的「管理者」属性࿱…...
Java高并发处理核心技术详解:从理论到实战
高并发处理能力是衡量系统性能的重要指标。Java作为企业级开发的主力语言,提供了丰富的并发编程工具和框架。 一、Java并发基础 1.1 Java内存模型(JMM) 主内存与工作内存:每个线程拥有独立的工作内存,通过JMM协议与主…...
单细胞测序数据分析试验设计赏析(二)
单细胞测序数据分析试验设计赏析(二) 这次的单细胞测序数据分析的试验设计是单细胞测序分析机器学习(with SHAP分析),也是常见的试验设计之一,重点是可以用于筛选鉴定基因调控网络,也可以是构建…...
Docker 服务搭建
💢欢迎来到张翊尘的开源技术站 💥开源如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Docker 服务搭建在 Ubuntu 上安装 Docker更新软件…...
4电池_基于开关电容的均衡
基于开关电容的均衡系统(Switched-Capacitor Equalization System) 开关电容均衡(Switched-Capacitor Equalization, SCE)是一种广泛应用于 电池组(如锂电池、超级电容组) 的主动均衡技术,通过电…...
Matlab/Simulink - BLDC直流无刷电机仿真基础教程(七) - 波形解析专题P2
Matlab/Simulink - BLDC直流无刷电机仿真基础教程(七) - 波形解析专题P2 前言一、缺相与相线错接解析二、电源电压波动三、电机感量及磁链变化四、负载突变及堵转五、换相时机不当及换相错误参考链接 前言 本系列文章分享如何使用Matlab的Simulink功能来…...
如何从GitHub上调研优秀的开源项目,并魔改应用于工作中?
在 Go 语言学习中,我们经常会去学习一些优秀的开源项目。但是学完之后,发现很快就忘记了或者学习效果并不好。学习一个开源项目最好的方式就是围绕这个开源项目进行实战。例如,直接魔改这个开源项目并应用于工作中。本文来介绍下如何调用&…...
【Java学习笔记】构造器
构造器(constructor)(又名构造方法) 作用:可以在创建对象时就初始化属性,注意不是创建 基本结构 [修饰符] 方法名(形参列表){方法体; }代码示例 public class 构造器 {public static void m…...
Redis 数据类型详解(一):String 类型全解析
文章目录 前言一、什么是 Redis 的 String 类型?二、常用命令1.SET2.GET3.MSET4.MGET5.INCR6.INCRBY7.INCRBYFLOAT8.SETNX9.SETEX 三、注意事项总结 前言 提示:这里可以添加本文要记录的大概内容: 在学习 Redis 的过程中,最基础也…...
JAVA---多态
面向对象三大特征:封装、继承、多态 多态 定义:同类型的对象,表现出的不同形态。 它允许不同类的对象通过同一个接口进行调用,并且在运行时根据实际对象类型执行不同的方法。 多态主要通过继承、接口和方法重写来实现。 表现形式…...
K8S的使用(部署pod\service)+安装kubesphere图形化界面使用和操作
master节点中通过命令部署一个tomcat 查看tomcat被部署到哪个节点上 在节点3中进行查看 在节点3中进行停止容器,K8S会重新拉起一个服务 如果直接停用节点3(模拟服务器宕机),则K8S会重新在节点2中拉起一个服务 暴露tomcat访…...
【Linux系统】第二节—基础指令(2)
hello ~ 好久不见 自己想要的快乐要自己好好争取! 云边有个稻草人-个人主页 Linux—本篇文章所属专栏—欢迎订阅—持续更新中 目录 本节课核心指令知识点总结 本节基本指令详解 07.man 指令 08.cp 指令 09.mv 指令 10.cat 指令 11.more 指令 12.less 指令 …...
Java设计模式: 实战案例解析
Java设计模式: 实战案例解析 在软件开发中,设计模式是一种用来解决特定问题的可复用解决方案。它们是经过实践验证的最佳实践,能够帮助开发人员设计出高质量、易于维护的代码。本文将介绍一些常见的Java设计模式,并通过实战案例解析它们在实际…...
ASP.NET MVC 入门与提高指南九
51. 时空数据处理与 MVC 应用拓展 51.1 时空数据概念 时空数据是指与时间和空间相关的数据,如地理信息系统(GIS)数据、交通流量数据、气象数据等,这些数据随时间和空间变化而变化。 51.2 在 MVC 应用中处理时空数据 地理信息系…...