问题描述
小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下:
- 如果分数中有三个或以上不同的分数,返回其中第三大的分数。
- 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。 请你帮小M根据给定的分数数组计算目标分数。
解题步骤
为了解决这个问题,可以通过以下步骤实现目标:
- 去重和排序:
- 由于题目需要提取“不同的分数”,我们可以使用集合(
std::set)来对原始分数进行去重。集合的数据结构特性可以自动去重并按升序排序,从而方便地提取排名分数。
- 由于题目需要提取“不同的分数”,我们可以使用集合(
- 分类讨论:
- 如果集合中有三个或以上不同的分数,可以按照顺序定位第三大的分数;
- 如果集合中不足三个分数,则直接取集合中的最大值作为结果。
- 优化实现:
- 在实现中,利用集合的反向迭代器(
rbegin)从最大值开始遍历,这样可以简化逻辑,直接从大到小定位第三大值,而不必重新转换排序顺序。
- 在实现中,利用集合的反向迭代器(
代码实现
#include <set>
#include <vector>
using namespace std;
int solution(int n, std::vector<int> nums) {
std::set<int> scorse;
for (int num : nums) {
scorse.insert(num);
}
if (scorse.size() >= 3) {
auto it = scorse.rbegin();
++it;
++it;
return *it;
} else {
return *scorse.rbegin();
}
}
int main() {
std::cout << (solution(3, {3, 2, 1}) == 1) << std::endl;
std::cout << (solution(2, {1, 2}) == 2) << std::endl;
std::cout << (solution(4, {2, 2, 3, 1}) == 1) << std::endl;
return 0;
}
思路总结
- 本题的核心在于合理使用集合去重并排序,结合分类讨论来简化实现逻辑。
- 通过反向迭代器从最大值开始,可以高效定位目标分数,避免多余的计算和排序操作。
- 这种方法不仅能够解决题目需求,还具有良好的时间和空间复杂度,适合处理较大规模的数据集。
集合知识补充
std::set 的迭代器
(1) 普通迭代器
-
使用普通迭代器(
begin()和end())可以从小到大遍历集合。 -
示例:
cpp 复制代码 std::set<int> s = {3, 1, 2}; for (auto it = s.begin(); it != s.end(); ++it) { std::cout << *it << " "; // 输出:1 2 3 }
(2) 反向迭代器
-
使用反向迭代器(
rbegin()和rend())可以从大到小遍历集合。 -
示例:
cpp 复制代码 std::set<int> s = {3, 1, 2}; for (auto it = s.rbegin(); it != s.rend(); ++it) { std::cout << *it << " "; // 输出:3 2 1 }
4. 自定义排序
默认情况下,std::set 是升序排列的。如果需要按照其他顺序(如降序)存储元素,可以使用自定义比较器。
示例:降序排列
cpp
复制代码
#include <set>
#include <iostream>
// 自定义比较器
struct Compare {
bool operator()(int a, int b) const {
return a > b; // 降序排列
}
};
int main() {
std::set<int, Compare> s = {3, 1, 2};
for (int x : s) {
std::cout << x << " "; // 输出:3 2 1
}
return 0;
}