题目
公司正在进行优秀项目组评比的初选工作,参赛者有小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
思路
排序:
对得分数组 a 进行升序排序,以便于后续处理。
遍历可能的分数线:
从数组的第一个元素到倒数第二个元素(即 a[0] 到 a[len-2]),逐个作为分数线 x 进行检查。
选择 a[len-2] 而不是 a[len-1] 是因为最后一个元素不可能作为分数线,因为它没有更大的分数来形成晋级的项目组。
计算晋级和淘汰数量:
对于每个分数线 x,计算大于 x 的项目组数量(晋级数量)和小于等于 x 的项目组数量(淘汰数量)。
晋级数量可以通过数组长度减去当前索引加一得到。
淘汰数量可以通过当前索引加一得到。
检查条件:
检查晋级和淘汰的数量是否都在 [m, n] 之间。
如果是,则记录当前分数线 x 并返回。
返回结果:
如果遍历完所有可能的分数线后都没有找到满足条件的分数线,则返回 -1。
代码
import java.util.Arrays;
public class Main {
public static int solution(int m, int n, int[] a) {
// 对得分数组进行排序
Arrays.sort(a);
int len = a.length;
// 遍历所有可能的分数线
for (int i = 0; i < len - 1; i++) {
int passCount = len - (i + 1); // 晋级数量
int failCount = i + 1; // 淘汰数量
// 检查晋级和淘汰的数量是否在 [m, n] 之间
if (passCount >= m && passCount <= n && failCount >= m && failCount <= n) {
return a[i]; // 返回当前分数线
}
}
// 如果没有找到满足条件的分数线,返回 -1
return -1;
}
public static void main(String[] args) {
System.out.println(solution(2, 3, new int[]{1, 2, 3, 5, 6, 4}) == 3);
System.out.println(solution(1, 2, new int[]{7, 8, 9, 3, 5}) == -1);
System.out.println(solution(1, 4, new int[]{7, 8, 9, 3, 5}) == 3);
System.out.println(solution(17, 79, new int[]{725,835,16,137,539,407,912,766,279,368,454,216,957,680,984,369,873,776,902,337,751,432,102,727,93,848,941,427,321,706,466,907,509,629,296,418,457,768,445,104,864,625,289,659,441,65,585,518,225,441,287,928,720,232,561,936,393,523,270,901,738,45,40,507,447,929,100,612,559,408,860,36,387,606,318,677,828,419,246,33,437,508,203,901,363,442,609,840,877,269,815,197,38,179,896,896,331,697,334,309,560,669,1,504,309,627,37,10,475,193,567,910,496,965,615,868,368,650,361,107}) == 368);
}
}