132题 优秀项目组评选 刷题笔记 | 豆包MarsCode AI刷题

75 阅读4分钟

问题描述

公司正在进行优秀项目组评比的初选工作,参赛者有小C、小U、小R、小S、小M和小F的项目组。评委会已经根据他们提交的材料完成了打分,各个项目组的得分分别是s1,s2,s3,,sks_1,s_2,s_3,\ldots,s_k。评委们希望设定一个初选晋级的分数线xx,让所有得分大于xx的项目组晋级,其他的项目组将被淘汰。此外,评委们希望晋级的项目组数量和淘汰的项目组数量都在区间[m,n][m,n]之间。 显然,这个分数线xx可能不存在,也可能存在多个满足条件的分数线。如果不存在满足条件的xx,则输出1-1;如果存在多个满足条件的分数线xx,则输出满足条件的最小分数线。

为了实现这个功能,我们需要根据题目的要求,选择一个合适的分数线 x,使得晋级的项目组数量和淘汰的项目组数量都在区间 [m, n] 之间。

解题思路:

  1. 输入说明

    • mn 是晋级项目组数量的下限和上限。
    • a 是一个数组,表示各个项目组的得分。
  2. 要求

    • 设定一个分数线 x,使得所有得分大于 x 的项目组晋级,其余的项目组淘汰。
    • 晋级的项目组数量应在 [m, n] 范围内。
    • 如果满足条件的分数线存在多个,则选择最小的分数线。
    • 如果不存在满足条件的分数线,则返回 -1

解决步骤:

  1. 排序得分数组

    • 将得分数组 a 排序,便于后续处理。
  2. 遍历可能的分数线

    • 分数线 x 可以是得分数组中每个项目组的得分值。假设我们选择一个分数线 x,则所有得分大于 x 的项目组将晋级,剩下的项目组将被淘汰。
  3. 计算晋级和淘汰人数

    • 对于每个分数线,计算有多少项目组的得分大于该分数线,即晋级的项目组数量。
    • 计算淘汰的项目组数量,即总人数减去晋级人数。
    • 如果晋级人数和淘汰人数都在 [m, n] 范围内,则该分数线是有效的。
  4. 选择最小分数线

    • 选择最小的符合条件的分数线 x
  5. 返回结果

    • 如果找到了符合条件的分数线,返回该分数线。
    • 如果找不到符合条件的分数线,返回 -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;
        
        // 遍历可能的分数线,检查每个可能的分数线 x
        for (int i = 0; i < len - 1; i++) {
            // 选择分数线 x 为 a[i]
            int x = a[i];
            
            // 计算晋级人数,即得分大于 x 的人数
            int passedCount = len - 1 - i;  // 所有得分大于 a[i] 的项目组数
            int eliminatedCount = i + 1;    // 所有得分小于等于 a[i] 的项目组数
            
            // 检查晋级人数和淘汰人数是否在 [m, n] 范围内
            if (passedCount >= m && passedCount <= n && eliminatedCount >= m && eliminatedCount <= n) {
                return x;
            }
        }
        
        // 如果没有符合条件的分数线
        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);
    }
}

解释:

  1. 排序

    • 我们对得分数组 a 进行排序,确保我们可以通过遍历数组来选择每个可能的分数线。
  2. 分数线选择

    • 对于每个得分 a[i],我们将其作为分数线 x
    • passedCount 是得分大于 x 的项目组数量,可以通过计算 len - 1 - i 来得到(ix 的索引,len 是数组长度)。
    • eliminatedCount 是得分小于等于 x 的项目组数量,是 i + 1
  3. 判断是否满足条件

    • 如果晋级和淘汰的项目组数量都在 [m, n] 范围内,则该分数线有效,返回当前分数线 x
  4. 返回 -1

    • 如果遍历所有可能的分数线都没有找到满足条件的,返回 -1

复杂度分析:

  • 时间复杂度:排序需要 O(k log k) 时间,其中 k 是数组的长度。遍历数组的时间是 O(k),因此总时间复杂度为 O(k log k)
  • 空间复杂度:排序操作使用了 O(k) 的额外空间。

总结

本题核心算法比较简单,只需要通过对得分进行排序并逐一验证每个可能的分数线,我们能够找到满足条件的最小分数线。如果没有满足条件的分数线,则返回 -1。