统计班级中的说谎者 | 豆包MarsCode AI刷题

56 阅读6分钟

引言

在编程学习与实践过程中,深入分析各类问题并总结解题思路和代码实现方式是提升能力的重要途径。本次针对题库中的统计班级里的说谎者展开详细剖析,并分享个人在探索过程中的学习心得。

题目具体描述

image.png

题目关键信息

1. 学生和成绩:

班级有 N 个学生,每个学生都有一个成绩 A_i。

我们需要判断哪些学生会说谎。

2. “说谎”的条件:

一个学生会说谎,当且仅当:

该学生的成绩小于或等于自己的成绩的学生数量 大于 成绩更高的学生数量。

换句话说,如果一个学生的成绩 A_i 的排名较低,且成绩相等或更低的学生的数量多于成绩高的学生数量,那么他会说谎。

3. “小于等于”和“大于”的定义:

小于等于他的学生数量:即成绩小于或等于该学生的学生数量。

大于他的学生数量:即成绩大于该学生的学生数量。

4. 目标:

计算并输出班级中有多少个学生会说谎。

5. 思考方式:

需要根据每个学生的成绩与其他学生的成绩比较,确定是否符合“说谎”的条件。

关键的操作是计算每个学生的成绩在班级中排名的相对位置,并基于这个排名来判断是否满足条件。

6. 数据结构和算法:

可以使用排序或计数排序来有效计算成绩小于等于某个学生成绩的学生数量。

排序后,便于根据学生成绩比较,直接获取排名和相关学生数量。

解题思路

要解决这个问题,我们需要明确 一个学生会说谎的条件,并且利用这一条件来判断每个学生是否符合要求。具体来说:  

1. 条件分析

学生说谎的条件是:

学生的成绩小于或等于他自己的成绩的学生数量 大于 比他成绩高的学生数量。

换句话说,一个学生的成绩排在班级中的前半部分,或者他有很多成绩相同的同学在他之前时,他才会说谎。

2. 步骤概述

我们需要计算出每个学生成绩小于等于他成绩的学生数量,然后与比他成绩高的学生数量进行比较。为了做到这一点,首先我们需要: 排序学生成绩。 对每个学生,计算 成绩小于等于该学生成绩的学生数量,并与 成绩大于该学生成绩的学生数量 比较。

3. 步骤分解

排序:首先对学生成绩进行排序。排序后,我们可以利用排序后的顺序,快速计算出每个学生成绩小于或等于他成绩的学生数量。

计算小于等于和大于学生数量:

对于每个学生 i,他的成绩在排序后的数组中的位置可以帮助我们确定:

成绩小于等于该学生的数量:就是排序数组中该学生的位置 i 加上相同成绩的学生数量。

成绩大于该学生的数量:可以通过总人数减去小于等于该学生的学生数量,得到大于该学生的学生数量。

判断说谎:

如果 成绩小于等于该学生的学生数量 大于 成绩大于该学生的学生数量,则该学生会说谎。

统计结果:最后,统计满足条件的学生数量。

4. 具体实现

排序:对学生成绩进行排序。

遍历每个学生:

对于每个学生,计算小于等于他成绩的学生数量。

比较小于等于该学生的学生数量和大于该学生的学生数量。

返回结果:输出满足条件的学生数。

Python代码

def solution(A):
    n = len(A)
    count = 0
    for index in range(n):
        less_equal_num = 0
        greater_num = 0
        for compare_index in range(n):
            if A[compare_index] <= A[index]:
                less_equal_num += 1
            if A[compare_index] > A[index]:
                greater_num += 1
        if less_equal_num > greater_num:
            count += 1
    return count

if __name__ == "__main__":
    assert solution([100, 100, 100]) == 3
    assert solution([2, 1, 3]) == 2
    assert solution([30, 1, 30, 30]) == 3
    assert solution([19, 27, 73, 55, 88]) == 3
    assert solution([19, 27, 73, 55, 88, 88, 2, 17, 22]) == 5
    

 

代码主要步骤

1. 函数定义和输入

def solution(A):

    n = len(A)

    count = 0

solution(A) 函数接收一个整数列表 A,表示学生的成绩。

n = len(A) 计算输入列表 A 的长度,表示学生的数量。

count = 0 初始化一个计数器,用于记录说谎的学生数量。

2. 遍历每个学生

for index in range(n):

使用 for 循环遍历学生列表 A 中的每个学生,index 表示当前正在处理的学生的位置。

3. 统计小于等于和大于该学生成绩的学生数量

less_equal_num = 0

greater_num = 0

for compare_index in range(n):

    if A[compare_index] <= A[index]:

        less_equal_num += 1

    if A[compare_index] > A[index]:

        greater_num += 1

对于每个学生 A[index],通过另一个 for 循环遍历所有学生成绩 A[compare_index] 来统计:

less_equal_num:统计成绩小于或等于当前学生成绩的学生数量。

greater_num:统计成绩大于当前学生成绩的学生数量。

如果 A[compare_index] <= A[index],则增加 less_equal_num 计数;如果 A[compare_index] > A[index],则增加 greater_num 计数。

4. 判断该学生是否说谎

if less_equal_num > greater_num:

    count += 1

对于每个学生,如果 less_equal_num > greater_num(即成绩小于或等于该学生的学生数量大于成绩更高的学生数量),则该学生会说谎,因此将 count 增加 1。

5. 返回最终结果

return count

最终返回 count,表示说谎的学生数量。

总结

暴力解法的简单和直观,但其效率较低,适用于数据规模小的情况。 对于更大的数据集,我们可以通过优化算法,如排序、前缀和等,来减少计算复杂度。 在处理复杂问题时,从暴力解法到优化思考是一个循序渐进的过程,能够帮助我们在实际问题中灵活运用不同的算法技巧。 通过这道题,我学到了如何分析问题的条件,然后根据条件逐步优化解决方案,并且理解了暴力解法与优化方案之间的权衡。