青训营X豆包MarsCode 代码详解 day7 | 豆包MarsCode AI 刷题

65 阅读3分钟

统计班级中的说谎者

问题描述

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

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


测试样例

样例1:

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

样例2:

输入:A = [2, 1, 3]
输出:2

样例3:

输入:A = [30, 1, 30, 30]
输出:3

样例4:

输入:A = [19, 27, 73, 55, 88]
输出:3

样例5:

输入:A = [19, 27, 73, 55, 88, 88, 2, 17, 22]
输出:5

问题分析

这道题目要求我们找出班级中会说谎的学生数量。根据题目描述,一个学生会说谎的条件是:成绩小于等于他的学生人数大于成绩比他高的学生人数。

解题思路

方法一:直接遍历(O(n²))

最直观的解法是对每个学生,遍历所有其他学生来统计分数关系。

    int n = A.length;
    int liars = 0;
    
    for (int i = 0; i < n; i++) {
        int lessOrEqual = 0;
        int greater = 0;
        
        // 统计与当前学生的分数关系
        for (int j = 0; j < n; j++) {
            if (A[j] <= A[i]) lessOrEqual++;
            else greater++;
        }
        
        if (lessOrEqual > greater) liars++;
    }
    
    return liars;
}

方法二:排序优化(O(n log n))

通过排序可以更高效地统计分数关系。

    int n = A.length;
    int[] sorted = A.clone();
    Arrays.sort(sorted);
    int liars = 0;
    
    for (int score : A) {
        // 二分查找当前分数位置
        int pos = Arrays.binarySearch(sorted, score);
        
        // 处理重复分数
        while (pos < n - 1 && sorted[pos + 1] == score) {
            pos++;
        }
        
        int lessOrEqual = pos + 1;
        int greater = n - lessOrEqual;
        
        if (lessOrEqual > greater) liars++;
    }
    
    return liars;
}

复杂度分析

方法一:

  • 时间复杂度:O(n²)

  • 空间复杂度:O(1)

方法二:

  • 时间复杂度:O(n log n)

  • 空间复杂度:O(n)

示例分析

让我们分析样例:[19, 27, 73, 55, 88]

  • 对于19:

  • 小于等于19的有:19 (1个)

  • 大于19的有:27,73,55,88 (4个)

  • 1 < 4,不说谎

  • 对于27:

  • 小于等于27的有:19,27 (2个)

  • 大于27的有:73,55,88 (3个)

  • 2 < 3,不说谎

  • 对于73:

  • 小于等于73的有:19,27,73,55 (4个)

  • 大于73的有:88 (1个)

  • 4 > 1,说谎

依此类推...

注意事项

  1. 处理重复分数:
  • 当有多个相同分数时,需要正确计算位置

  • 二分查找后需要处理重复元素

  • 边界情况:

  • 所有分数相同的情况

  • 只有一个学生的情况

  • 计数判断:

  • 必须严格大于,等于不算说谎

  • 包含自己的分数在内

总结

  • 这道题目可以用多种方法解决,关键是找到高效的方式来统计分数关系。

  • 虽然直接遍历方法简单直观,但在处理大规模数据时效率较低。

  • 排序优化的方法虽然需要额外空间,但大大提高了时间效率。

  • 实际应用中,如果数据规模较大,建议使用排序优化的方法。