题目理解
题目要求计算一个班级中有多少学生会“说谎”。判定说谎的规则如下:
- 如果某学生的分数 小于等于 他的学生数量 多于 比他分数高的学生数量,那么这个学生会说谎**。
从数学角度描述:
- 排序分数数组 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。
- 当 X>YX > YX>Y 时,学生说谎。
解题思路
-
排序分数数组: 首先对分数数组 AAA 排序。
-
计算中位数:
- 中位数是分割数组的关键值。
- 排序后的数组中,小于等于中位数的元素数量 XXX 是容易确定的。
-
计算说谎人数:
- 如果学生分数小于等于中位数,那么 X>YX > YX>Y 必然成立(中位数的性质)。
- 因此,说谎人数为分数小于等于中位数的学生人数。
-
优化查找中位数:
- 使用快速选择(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 刷题的过程中学习到以下内容:
-
快速选择算法(Quickselect) :
- 类似于快速排序,时间复杂度为 O(n)O(n)O(n),在查找中位数等场景十分高效。
-
中位数的特性:
- 中位数在有序数组中将其分为两个部分,左边元素小于等于中位数,右边元素大于中位数。
-
优化逻辑:
- 排序的完整性不总是必要,合理运用局部排序(如快速选择)可以降低时间复杂度。
学习计划
-
制定刷题计划:
- 按主题(如排序、动态规划)分模块刷题。
- 每周固定复习上周错题,分析薄弱点。
-
利用错题进行针对性学习:
- 保存错题到专门的分类文件夹,详细记录错误原因。
- 将错题对应知识点补充到笔记。
-
高效学习方法:
- 先理解题目核心,再优化代码。
- 定期进行难题专项训练,突破瓶颈。
工具运用建议
-
结合MarsCode AI:
- 通过交互式反馈,理解算法复杂度。
- 使用模拟测试,提高代码鲁棒性。
-
辅助资源:
- 配合教材和网络资源学习核心算法。
- 在实际项目中应用刷题学到的技能,巩固所学知识。
此题示例展示了如何利用算法高效解决实际问题,希望能对其他入门同学提供帮助!