题目分析:寻找第三大不同分数 这道题的目标是帮助小M找到一场比赛中排名第三的分数。如果比赛中没有三个不同分数,那么小M将取最高分作为目标。这类问题的核心在于对数组进行排序并统计不同元素,既考察排序逻辑,也要求对不同值的统计有清晰的实现。
解题思路与分析 从题目中可以提炼出以下关键点:
排序和去重: 由于我们要找的是第三大的分数,排序是核心操作。同时需要统计不同分数的数量,这里隐含了对重复值的处理需求。
返回逻辑:
如果分数中有三个或以上不同分数,返回第三大的分数。 如果不同分数只有两个或更少,直接返回最大的分数。 实现方式:
先对数组进行升序排序,方便从后向前遍历寻找不同分数。 从末尾向前统计不同分数,找到第三个不同的值后立即返回。 如果未找到三个不同分数,则返回数组中最大的值 代码实现分析 排序部分 代码中采用了冒泡排序对数组进行升序排序:
for (i = 0; i < n; i++) {
for (j = 0; j < n - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
t = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = t;
}
}
}
冒泡排序虽然时间复杂度为 O(n2)O(n^2)O(n2),但它简单易懂,适合小规模数据。排序后,数组从小到大排列,方便后续统计不同分数。
for (i = n - 1; i > 0; i--) {
if (nums[i] != nums[i - 1]) {
count++;
}
if (count == 3) {
return nums[i - 1];
}
}
每当遇到一个不同的分数,count 加一。 当 count 达到 3 时,当前值即为第三大的分数,立即返回。 如果遍历结束后 count 小于 3,说明不同分数不足三种,直接返回数组中的最大值,即 nums[n-1]。
测试案例分析 测试用例 1:典型场景 输入: n = 6, nums = {100, 90, 90, 80, 70, 70} 执行流程:
排序后数组为:{70, 70, 80, 90, 90, 100}。 从末尾开始统计不同分数: 最大值 100,不同分数 1。 次大值 90,不同分数 2。 第三大值 80,不同分数 3,返回 80。 输出:80 测试用例 2:不足三个不同分数 输入: n = 5, nums = {90, 90, 90, 90, 80} 执行流程:
排序后数组为:{80, 90, 90, 90, 90}。 从末尾开始统计不同分数: 最大值 90,不同分数 1。 次大值 80,不同分数 2。 没有第三个不同分数,返回最大值 90。 输出:90 测试用例 3:所有分数相同 输入: n = 4, nums = {50, 50, 50, 50} 执行流程:
排序后数组为:{50, 50, 50, 50}。 从末尾开始统计不同分数: 最大值 50,不同分数 1。 没有第二个或第三个不同分数,返回最大值 50。 输出:50 测试用例 4:所有分数不同 输入: n = 5, nums = {10, 20, 30, 40, 50} 执行流程:
排序后数组为:{10, 20, 30, 40, 50}。 从末尾开始统计不同分数: 最大值 50,不同分数 1。 次大值 40,不同分数 2。 第三大值 30,不同分数 3,返回 30。 输出:30
从问题到实现的感悟:解答这道题让我深刻感受到排序和统计在实际问题中的重要性。排序不仅仅是算法的一部分,更是整理混乱数据的重要工具;统计不同值则是对数组特性的深入挖掘。在实现过程中,虽然使用了冒泡排序,但也思考了更高效的替代方案,比如 C++ 的内置排序函数 std::sort,可以将时间复杂度降低到 O(nlogn)。然而,选择手写冒泡排序,也让我对算法的基础原理有了更清晰的认知。通过不同的测试用例,我体会到边界情况的重要性。无论是分数全部相同还是不足三个不同分数,这些都能帮助验证代码的正确性和鲁棒性。