【c++】【leetcode506】相对名次,用map实现

该博客讨论了如何利用红黑树实现一个排名系统,特别是在处理竞赛成绩时分配金银铜牌的情况。当输入的分数数量为n时,通过创建一个映射存储分数及其对应的排名,然后遍历映射来确定前三名的奖牌归属。代码中展示了如何在O(n*logn)的时间复杂度内完成这一过程。

在这里插入图片描述

解题思路

map底层实现是一棵红黑树,按照key值升序排列,题目给出分数各自不同
分情况讨论:

  • n=1:这个人就是金牌
  • n=2:两个人比较一下得出金银牌
  • n>=3
  1. 用一个map<int,int>temp来存放分数和下标值(下标值代表第几位)。根据排序的结果从第1到n-3位的名次就是他们分数的名次,我们已知map是升序排列,因此在map中的第一位名次是n,以此类推。
  2. 在map中的最后三位分别是金银铜牌。

map查找的时间复杂度是O(logn),最终的时间复杂度是O(n*logn)

代码

class Solution {
public:
    vector<string> findRelativeRanks(vector<int>& score) {
        int n=score.size();
        vector<string>answer(n);
        if(n==1){answer[0]="Gold Medal";return answer;}
        if(n==2)
        {
            answer[0]=score[0]>score[1]?"Gold Medal":"Silver Medal";
            answer[1]=score[0]<score[1]?"Gold Medal":"Silver Medal";
            return answer;
        }
        //n>=3的情况
        map<int,int>temp;
        for(int i=0;i<n;i++){temp[score[i]]=i;}//关键字是分数,i是第几位
        auto it=temp.begin();//it->first is score,it->second是原数组的标号
        for(int i=0;i<n-3;it++,i++){answer[it->second]=to_string(n-i);}
        //最后三位分别为金银铜牌
        answer[it->second]="Bronze Medal";it++;
        answer[it->second]="Silver Medal";it++;
        answer[it->second]="Gold Medal";
        return answer;
    }
};
### POJ1442 名次树问C++实现时间复杂度分析 POJ1442 名次树(Rank Tree)问涉及构建和查询一种特殊的数据结构,通常称为平衡二叉搜索树或基于数组的堆式结构。在C++实现时,需要对插入、删除、查找等操作的时间复杂度进行详细分析。 #### 1. 插入操作的时间复杂度 在名次树中,插入一个新元素的操作通常涉及维护树的平衡性。如果使用的是自平衡二叉搜索树(如AVL树或红黑树),插入操作的时间复杂度为 \(O(\log n)\) [^1]。这是因为每次插入后最多需要调整 \(O(\log n)\) 层节点以恢复树的平衡性。 #### 2. 删除操作的时间复杂度 类似地,删除操作也需要维护树的平衡性。在自平衡二叉搜索树中,删除操作的时间复杂度同样为 \(O(\log n)\) [^1]。删除操作可能涉及重新分配子树,但这仍然可以通过 \(O(\log n)\) 的调整完成。 #### 3. 查找操作的时间复杂度 查找操作在平衡二叉搜索树中的时间复杂度为 \(O(\log n)\) [^1],因为从根节点到目标节点的路径长度最多为树的高度,而平衡二叉树的高度为 \(O(\log n)\)。 #### 4. 构建整个树的时间复杂度 如果初始时需要将 \(n\) 个元素插入到空树中,则总的时间复杂度为 \(O(n \log n)\) [^1]。这是因为在插入每个元素时,都需要执行 \(O(\log n)\) 的调整操作。 #### 5. 查询排名的时间复杂度 在名次树中,查询某个值的排名通常需要从根节点开始向下遍历,并根据左子树的大小计算排名。假设树是完全平衡的,则查询排名的时间复杂度为 \(O(\log n)\) [^1]。 #### 6. 综合时间复杂度 综合来看,名次树的基本操作(插入、删除、查找、排名查询)的时间复杂度均为 \(O(\log n)\),而在构建整个树时的时间复杂度为 \(O(n \log n)\)。 ```cpp #include <bits/stdc++.h> using namespace std; struct Node { int val, size; Node *left, *right; Node(int v) : val(v), size(1), left(nullptr), right(nullptr) {} }; int getSize(Node* node) { return node ? node->size : 0; } void updateSize(Node* node) { if (node) node->size = 1 + getSize(node->left) + getSize(node->right); } Node* rotateRight(Node* y) { Node* x = y->left; Node* T2 = x->right; x->right = y; y->left = T2; updateSize(y); updateSize(x); return x; } Node* rotateLeft(Node* x) { Node* y = x->right; Node* T2 = y->left; y->left = x; x->right = T2; updateSize(x); updateSize(y); return y; } Node* splay(Node* root, int key) { if (!root || root->val == key) return root; if (key < root->val) { if (!root->left) return root; if (key < root->left->val) { root->left->left = splay(root->left->left, key); root = rotateRight(root); } else if (key > root->left->val) { root->left->right = splay(root->left->right, key); if (root->left->right) root->left = rotateLeft(root->left); } return root->left ? rotateRight(root) : root; } else { if (!root->right) return root; if (key < root->right->val) { root->right->left = splay(root->right->left, key); if (root->right->left) root->right = rotateRight(root->right); } else if (key > root->right->val) { root->right->right = splay(root->right->right, key); root = rotateLeft(root); } return root->right ? rotateLeft(root) : root; } } Node* insert(Node* root, int key) { if (!root) return new Node(key); root = splay(root, key); if (root->val == key) return root; Node* newNode = new Node(key); if (key < root->val) { newNode->right = root; newNode->left = root->left; root->left = nullptr; } else { newNode->left = root; newNode->right = root->right; root->right = nullptr; } updateSize(newNode); return newNode; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值