游戏排名第三大的分数问题 | 豆包MarsCode AI刷题

145 阅读3分钟

问题描述

小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下:

  1. 如果分数中有三个或以上不同的分数,返回其中第三大的分数。
  2. 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。 请你帮小M根据给定的分数数组计算目标分数。

解题步骤

为了解决这个问题,可以通过以下步骤实现目标:

  1. 去重和排序
    • 由于题目需要提取“不同的分数”,我们可以使用集合(std::set)来对原始分数进行去重。集合的数据结构特性可以自动去重并按升序排序,从而方便地提取排名分数。
  2. 分类讨论
    • 如果集合中有三个或以上不同的分数,可以按照顺序定位第三大的分数;
    • 如果集合中不足三个分数,则直接取集合中的最大值作为结果。
  3. 优化实现
    • 在实现中,利用集合的反向迭代器(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;
}