问题分析
这道题目要求我们找到一个分数线 xxx,使得:
- 晋级人数(得分大于 xxx)在区间 [m,n][m, n][m,n] 之间。
- 淘汰人数(得分小于等于 xxx)也在区间 [m,n][m, n][m,n] 之间。
- 如果满足条件的分数线 xxx 存在多个,返回最小的 xxx。
- 如果不存在满足条件的分数线,返回 −1-1−1。
解决思路
-
排序数组:
- 我们首先对分数数组 aaa 进行升序排序。
- 这样可以方便地通过数组索引快速判断当前分数线 xxx 的晋级人数和淘汰人数。
-
枚举所有可能的分数线:
- 分数线 xxx 的候选值只能是数组 aaa 中的某个得分。因为得分位于两项之间的值并不会改变晋级或淘汰的分组。
- 因此,我们只需要遍历数组 aaa,逐一将其每个元素作为候选分数线 xxx。
-
计算晋级人数和淘汰人数:
-
对于一个给定的分数线 x=a[i]x = a[i]x=a[i]:
- 晋级人数:passed=k−(i+1)\text{passed} = k - (i + 1)passed=k−(i+1),表示 a[i+1],a[i+2],…,a[k−1]a[i+1], a[i+2], \dots, a[k-1]a[i+1],a[i+2],…,a[k−1] 的个数。
- 淘汰人数:eliminated=i+1\text{eliminated} = i + 1eliminated=i+1,表示 a[0],a[1],…,a[i]a[0], a[1], \dots, a[i]a[0],a[1],…,a[i] 的个数。
-
-
验证条件:
-
如果同时满足:
- m≤passed≤nm \leq \text{passed} \leq nm≤passed≤n
- m≤eliminated≤nm \leq \text{eliminated} \leq nm≤eliminated≤n
-
那么当前分数线 x=a[i]x = a[i]x=a[i] 是一个可行解。
-
-
选择最小分数线:
- 我们从小到大遍历数组 aaa,一旦找到满足条件的分数线 xxx,就立即返回。这样保证了返回的分数线是最小的。
-
返回结果:
- 如果遍历完数组仍未找到满足条件的分数线,则返回 −1-1−1。
代码详解
def find_score_threshold(m: int, n: int, a: list) -> int:
# 对数组排序
a.sort()
length = len(a)
result = -1
# 遍历每个分数线
for i in range(length):
# 当前分数线为 a[i]
x = a[i]
# 晋级人数(得分 > x)
passed = length - (i + 1)
# 淘汰人数(得分 <= x)
eliminated = i + 1
# 检查条件
if m <= passed <= n and m <= eliminated <= n:
result = x
break # 找到第一个符合条件的最小分数线,直接退出
return result
代码核心逻辑
-
排序:
a.sort()- 将分数数组按从小到大的顺序排列,方便后续的遍历和人数计算。
-
遍历数组:
for i in range(length): x = a[i] # 当前分数线- 每次将数组中的一个元素 a[i]a[i]a[i] 作为当前分数线。
-
计算人数:
passed = length - (i + 1) # 晋级人数 eliminated = i + 1 # 淘汰人数- 晋级人数为数组中得分大于当前分数线的元素个数。
- 淘汰人数为数组中得分小于等于当前分数线的元素个数。
-
条件验证:
if m <= passed <= n and m <= eliminated <= n: result = x break # 找到第一个满足条件的分数线,立即退出- 同时验证晋级人数和淘汰人数是否都在区间 [m,n][m, n][m,n] 之间。
- 如果满足条件,记录分数线并退出循环。
-
返回结果:
return result- 如果找到符合条件的分数线,返回结果;如果没有,返回 −1-1−1。
测试用例详解
示例 1
输入:
m = 2, n = 3, a = [1, 2, 3, 5, 6, 4]
排序后:
a = [1, 2, 3, 4, 5, 6]
枚举分数线:
- x=1x = 1x=1:晋级人数 = 5,淘汰人数 = 1,不满足条件。
- x=2x = 2x=2:晋级人数 = 4,淘汰人数 = 2,不满足条件。
- x=3x = 3x=3:晋级人数 = 3,淘汰人数 = 3,满足条件。
输出:
3
示例 2
输入:
m = 1, n = 2, a = [7, 8, 9, 3, 5]
排序后:
a = [3, 5, 7, 8, 9]
枚举分数线:
- x=3x = 3x=3:晋级人数 = 4,淘汰人数 = 1,不满足条件。
- x=5x = 5x=5:晋级人数 = 3,淘汰人数 = 2,不满足条件。
- x=7x = 7x=7:晋级人数 = 2,淘汰人数 = 3,不满足条件。
- x=8x = 8x=8:晋级人数 = 1,淘汰人数 = 4,不满足条件。
输出:
-1
示例 3
输入:
m = 1, n = 4, a = [7, 8, 9, 3, 5]
排序后:
a = [3, 5, 7, 8, 9]
枚举分数线:
- x=3x = 3x=3:晋级人数 = 4,淘汰人数 = 1,满足条件。
输出:
3
时间复杂度与空间复杂度
-
时间复杂度:
- 排序:O(klogk)O(k \log k)O(klogk),其中 kkk 是数组的长度。
- 遍历数组:O(k)O(k)O(k)。
- 总时间复杂度为 O(klogk)O(k \log k)O(klogk)。
-
空间复杂度:
- 使用了少量临时变量,空间复杂度为 O(1)O(1)O(1)。
总结
通过排序和枚举,我们可以高效地找到满足条件的最小分数线,代码逻辑清晰,时间复杂度和空间复杂度都符合要求。