青训营X豆包MarsCode 技术训练营第一课 | 豆包MarsCode AI 刷题

30 阅读2分钟

问题描述

在小C的班级里,有 N 个学生,每个学生的成绩是 A_i。小C发现了一件有趣的事:当且仅当某个学生的成绩小于或等于自己的有更多人时,这个学生会说谎。换句话说,如果分数小于等于他的学生数量大于比他分数高的学生数量,则他会说谎。

现在,小C想知道班里有多少个学生会说谎。

样例1:

输入:A = [100, 100, 100]
输出:3

解题思路

要解决这个问题,我们需要确定有多少学生的成绩是这样的:成绩小于或等于他们的学生数量大于成绩高于他们的学生的。

  1. 排序:首先对成绩数组 A 进行排序。排序后,相同的成绩会相邻排列。

  2. 确定中间成绩:找到排序后数组的中间成绩 mid。这个成绩是中间值,即左边有 left 个成绩,右边有 right 个成绩。

  3. 调整 leftright 指针

    • 如果 left 指针的前一个成绩与 mid 相同,说明有多个相同的成绩,需要向左移动 left 指针,直到遇到不同的成绩。
    • 如果 right 指针的后一个成绩与 mid 相同,同样需要向右移动 right 指针,直到遇到不同的成绩。
  4. 计算说谎的学生数量

    • left 指针现在指向最后一个成绩小于 mid 的学生。
    • right 指针现在指向第一个成绩大于 mid 的学生。
    • 如果成绩大于 mid 的学生数量少于成绩小于等于 mid 的学生数量,那么成绩为 mid 的学生就会说谎。因此,需要计算 right-left-1(不包括 mid 本身)。
    • 除了 mid 成绩的学生外,所有成绩大于 mid 的学生也会说谎,因此需要加上 A.length-right
  5. 返回说谎的学生总数:将上述两部分相加,得到说谎学生的总数。

例如根据样例:

输入:A = [25,12,8,19,19,16,20]
输出:4

排序后的数组是 [8, 12, 16, 19, 19, 20, 25]。中间成绩是19left 指针指向第3个位置(成绩16),right 指针指向第5个位置(成绩20)。成绩小于或等于19的学生数量是4,成绩大于19的学生数量是2。由于4大于2,中间成绩的学生说谎,另外还有3个成绩大于19的学生也说谎。因此,说谎的学生总数是4代码

public static int solution(int[] A) {
        int res=0;
        Arrays.sort(A);
        int left=A.length/2, right=A.length/2;
        int mid=A[A.length/2];
        if(left>0&&A[left-1]==A[left]){
            while(left>0&&A[left-1]==mid){
                left--;
            }
        }
        if(right<A.length-1&&A[right]==A[right+1]){
            while(right<A.length-1&&A[right+1]==mid){
                right++;
            }
        }
        left-=1;
        right+=1;
        if(A.length-right<right){
            res=res+right-left-1;
        }
        res+=A.length-right;
        return res;
    }
    ```