问题描述
公司正在进行优秀项目组评比的初选工作,参赛者有小C、小U、小R、小S、小M和小F的项目组。评委会已经根据他们提交的材料完成了打分,各个项目组的得分分别是s1,s2,s3,…,sks1,s2,s3,…,sk。评委们希望设定一个初选晋级的分数线xx,让所有得分大于xx的项目组晋级,其他的项目组将被淘汰。此外,评委们希望晋级的项目组数量和淘汰的项目组数量都在区间[m,n][m,n]之间。
显然,这个分数线xx可能不存在,也可能存在多个满足条件的分数线。如果不存在满足条件的xx,则输出−1−1;如果存在多个满足条件的分数线xx,则输出满足条件的最小分数线。
测试样例
示例 1:
输入:
m = 2, n = 3, a = [1, 2, 3, 5, 6, 4]
输出:3
示例 2:
输入:
m = 1, n = 2, a = [7, 8, 9, 3, 5]
输出:-1
示例 3:
输入:
m = 1, n = 4, a = [7, 8, 9, 3, 5]
输出:3
题目分析
我们需要找到一个分数线 xx,使得所有得分大于 xx 的项目组数量在区间 [m,n][m, n] 内,同时满足以下条件:
- 如果不存在这样的 xx,输出 −1-1。
- 如果有多个满足条件的 xx,输出最小的 xx。
解题思路
-
排序:先对数组 aa 进行排序,以便于后续操作。
-
枚举分数线 xx:
- 枚举每个可能的分数 xx(实际上就是从数组 aa 中的所有分数中选择)。
- 计算得分大于 xx 的项目组数量。
- 判断该数量是否在区间 [m,n][m, n] 内。
-
返回结果:如果找到满足条件的 xx,输出最小的 xx;否则输出 −1-1。
算法复杂度
- 时间复杂度:排序需要 O(klogk)O(k \log k),枚举每个可能的 xx 需要 O(k)O(k),整体复杂度为 O(klogk)O(k \log k)。
- 空间复杂度:O(1)O(1)(不需要额外空间)。
代码实现
def findThreshold(m, n, a):
a.sort() # 对数组从小到大排序
k = len(a)
# 遍历数组中每一个可能的分数线 x
for i in range(k):
x = a[i]
# 计算得分大于 x 的项目组数量
num_greater = k - i - 1 # a[i+1:] 的长度
# 判断是否符合条件
if m <= num_greater <= n:
return x
# 如果没有满足条件的 x,返回 -1
return -1
# 测试样例
print(findThreshold(2, 3, [1, 2, 3, 5, 6, 4])) # 输出:3
print(findThreshold(1, 2, [7, 8, 9, 3, 5])) # 输出:-1
print(findThreshold(1, 4, [7, 8, 9, 3, 5])) # 输出:3
示例解释
示例 1:
-
输入:m=2,n=3,a=[1,2,3,5,6,4]m = 2, n = 3, a = [1, 2, 3, 5, 6, 4]
-
排序后:1,2,3,4,5,61, 2, 3, 4, 5, 6
-
枚举 xx:
- x=1x = 1,得分大于 11 的数量是 5,不在区间 [2,3][2, 3]。
- x=2x = 2,得分大于 22 的数量是 4,不在区间 [2,3][2, 3]。
- x=3x = 3,得分大于 33 的数量是 3,满足条件。
-
输出:33。
示例 2:
-
输入:m=1,n=2,a=[7,8,9,3,5]m = 1, n = 2, a = [7, 8, 9, 3, 5]
-
排序后:3,5,7,8,93, 5, 7, 8, 9
-
枚举 xx:
- x=3x = 3,得分大于 33 的数量是 4,不在区间 [1,2][1, 2]。
- x=5x = 5,得分大于 55 的数量是 3,不在区间 [1,2][1, 2]。
- x=7x = 7,得分大于 77 的数量是 2,满足条件。
-
输出:−1-1(无满足的分数线)。
示例 3:
-
输入:m=1,n=4,a=[7,8,9,3,5]m = 1, n = 4, a = [7, 8, 9, 3, 5]
-
排序后:3,5,7,8,93, 5, 7, 8, 9
-
枚举 xx:
- x=3x = 3,得分大于 33 的数量是 4,满足条件。
-
输出:33。