统计说谎的人| 豆包MarsCode AI刷题

79 阅读3分钟

题目理解

题目要求计算一个班级中有多少学生会“说谎”。判定说谎的规则如下:

  • 如果某学生的分数 小于等于 他的学生数量 多于 比他分数高的学生数量,那么这个学生会说谎**。

从数学角度描述:

  1. 排序分数数组 AAA,对于每个分数 A[i]A[i]A[i],找到满足 A[j]≤A[i]A[j] \leq A[i]A[j]≤A[i] 的人数 XXX,以及满足 A[j]>A[i]A[j] > A[i]A[j]>A[i] 的人数 YYY。
  2. 当 X>YX > YX>Y 时,学生说谎。

解题思路

  1. 排序分数数组: 首先对分数数组 AAA 排序。

  2. 计算中位数

    • 中位数是分割数组的关键值。
    • 排序后的数组中,小于等于中位数的元素数量 XXX 是容易确定的。
  3. 计算说谎人数

    • 如果学生分数小于等于中位数,那么 X>YX > YX>Y 必然成立(中位数的性质)。
    • 因此,说谎人数为分数小于等于中位数的学生人数。
  4. 优化查找中位数

    • 使用快速选择(Quickselect)算法代替全量排序,时间复杂度降为 O(n)O(n)O(n)。

代码详解

以下为解析代码的完整逻辑及注释:

python
复制代码
def partition(arr, low, high):
    """分区函数,用于快速选择"""
    pivot = arr[high]  # 选择最后一个元素作为基准
    i = low
    for j in range(low, high):
        if arr[j] < pivot:
            arr[i], arr[j] = arr[j], arr[i]
            i += 1
    arr[i], arr[high] = arr[high], arr[i]
    return i

def quickselect(arr, low, high, k):
    """快速选择算法,返回第 k 小的元素"""
    if low == high:
        return arr[low]
    
    pivot_index = partition(arr, low, high)
    
    if k == pivot_index:
        return arr[k]
    elif k < pivot_index:
        return quickselect(arr, low, pivot_index - 1, k)
    else:
        return quickselect(arr, pivot_index + 1, high, k)

def find_median(arr):
    """计算数组中位数"""
    n = len(arr)
    if n % 2 == 1:
        return quickselect(arr, 0, n - 1, n // 2)
    else:
        mid1 = quickselect(arr, 0, n - 1, n // 2 - 1)
        mid2 = quickselect(arr, 0, n - 1, n // 2)
        return (mid1 + mid2) / 2

def solution(A):
    """主函数,计算班级中说谎学生的数量"""
    median = find_median(A)  # 找到中位数
    count = sum(i <= median for i in A)  # 统计小于等于中位数的分数数量
    return count

if __name__ == "__main__":
    # 测试用例
    print(solution([100, 100, 100]) == 3)
    print(solution([2, 1, 3]) == 2)
    print(solution([30, 1, 30, 30]) == 3)
    print(solution([19, 27, 73, 55, 88]) == 3)
    print(solution([19, 27, 73, 55, 88, 88, 2, 17, 22]) == 5)

知识总结

在使用豆包MarsCode AI 刷题的过程中学习到以下内容:

  1. 快速选择算法(Quickselect)

    • 类似于快速排序,时间复杂度为 O(n)O(n)O(n),在查找中位数等场景十分高效。
  2. 中位数的特性

    • 中位数在有序数组中将其分为两个部分,左边元素小于等于中位数,右边元素大于中位数。
  3. 优化逻辑

    • 排序的完整性不总是必要,合理运用局部排序(如快速选择)可以降低时间复杂度。

学习计划

  1. 制定刷题计划

    • 按主题(如排序、动态规划)分模块刷题。
    • 每周固定复习上周错题,分析薄弱点。
  2. 利用错题进行针对性学习

    • 保存错题到专门的分类文件夹,详细记录错误原因。
    • 将错题对应知识点补充到笔记。
  3. 高效学习方法

    • 先理解题目核心,再优化代码。
    • 定期进行难题专项训练,突破瓶颈。

工具运用建议

  1. 结合MarsCode AI

    • 通过交互式反馈,理解算法复杂度。
    • 使用模拟测试,提高代码鲁棒性。
  2. 辅助资源

    • 配合教材和网络资源学习核心算法。
    • 在实际项目中应用刷题学到的技能,巩固所学知识。

此题示例展示了如何利用算法高效解决实际问题,希望能对其他入门同学提供帮助!