问题描述
公司需要为优秀项目组评比初选设置一个晋级分数线 x,满足以下条件:
- 所有得分大于 x 的项目组晋级,其数量在区间 [m,n] 内。
- 所有得分不大于 x 的项目组被淘汰,其数量也在区间 [m,n] 内。
需要输出满足条件的 最小分数线 x。
- 如果不存在满足条件的 x,返回 −1。
- 如果有多个满足条件的 x,输出 最小值。
解题思路
- 排序和去重:
- 首先对数组 a 进行排序,得到按分数升序排列的列表。
- 提取唯一分数值,用于枚举可能的分数线 x。
- 枚举分数线 x:
- 对每个可能的分数线 x,统计得分 大于 x 的项目组数量(即晋级数量)。
- 检查晋级数量是否符合区间 [m,n]。
- 选择最小有效分数线:
- 若某个分数线 x 满足条件,记录为当前最小的有效分数线。
- 输出结果:
- 如果找到了满足条件的分数线,返回最小值;否则返回 −1。
算法步骤
- 初始化:
- 对数组 a 排序,提取唯一分数值集合 unique_scores。
- 设置变量 min_valid_x 表示最小有效分数线,初始为正无穷。
- 枚举分数线:
- 遍历 unique_scores 中的每个分数 score:
- 计算得分大于当前分数线的项目组数量 count_above。
- 判断 count_above 是否在区间 [m,n] 内。
- 若符合条件,则更新 min_valid_x=min(min_valid_x,score)。
- 遍历 unique_scores 中的每个分数 score:
- 返回结果:
- 若找到有效分数线,返回 min_valid_x。
- 若未找到有效分数线,返回 −1。
代码实现
def solution(m: int, n: int, a: list) -> int:
# 排序并获取唯一分数集合
a.sort()
unique_scores = sorted(set(a))
# 初始化最小有效分数线
min_valid_x = float('inf')
# 遍历每个可能的分数线
for score in unique_scores:
# 统计得分大于当前分数线的项目组数量
count_above = sum(1 for s in a if s > score)
# 检查数量是否在 [m, n] 范围内
if m <= count_above <= n:
min_valid_x = min(min_valid_x, score)
# 返回结果
return min_valid_x if min_valid_x != float('inf') else -1
if __name__ == '__main__':
print(solution(2, 3, [1, 2, 3, 5, 6, 4]) == 3) # 输出 3
print(solution(1, 2, [7, 8, 9, 3, 5]) == -1) # 输出 -1
print(solution(1, 4, [7, 8, 9, 3, 5]) == 3) # 输出 3
测试解析
测试 1
输入:m = 2, n = 3, a = [1, 2, 3, 5, 6, 4]
- 排序后:a = [1, 2, 3, 4, 5, 6]。
- 唯一分数:[1, 2, 3, 4, 5, 6]。
- 遍历可能分数线:
- x = 1:大于 1 的数量为 5,不符合 [m, n]。
- x = 2:大于 2 的数量为 4,不符合。
- x = 3:大于 3 的数量为 3,符合 [2, 3]。
- 其他分数不满足条件。
输出:x = 3。
测试 2
输入:m = 1, n = 2, a = [7, 8, 9, 3, 5]
- 排序后:a = [3, 5, 7, 8, 9]。
- 唯一分数:[3, 5, 7, 8, 9]。
- 遍历可能分数线:
- x = 3:大于 3 的数量为 4,不符合 [1, 2]。
- x = 5:大于 5 的数量为 3,不符合。
- 其他分数不满足条件。
输出:−1。
测试 3
输入:m = 1, n = 4, a = [7, 8, 9, 3, 5]
- 排序后:a = [3, 5, 7, 8, 9]。
- 唯一分数:[3, 5, 7, 8, 9]。
- 遍历可能分数线:
- x = 3:大于 3 的数量为 4,符合 [1, 4]。
输出:x = 3。
- x = 3:大于 3 的数量为 4,符合 [1, 4]。
复杂度分析
- 时间复杂度:
- 排序时间 O(klogk),其中 k 是数组长度。
- 遍历唯一分数集合 O(k×u),其中 u 是去重后唯一分数数量。
总时间复杂度为 O(klogk+k×u)。
- 空间复杂度:
排序和辅助变量使用固定空间,空间复杂度为 O(1)。