Leetcode:h指数

📟作者主页:慢热的陕西人

🌴专栏链接:力扣刷题日记

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

文章目录

题目链接

274. H 指数 - 力扣(LeetCode)

题目描述

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数 。

根据维基百科上 h 指数的定义:h 代表"高引用次数" ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。

方法一:排序

解题思路

理解了题意以后我们可以对h数总结为如下几点:

a. 0 <= h < citationsi.size() : h数一定是小于论文数量的

b. h = min(i, 当前数组中第i大的元素):即至少 有 h 篇论文被引用次数大于等于 h

基于上述两点我们可以先将数组排序然后遍历数组即可得到答案!

代码

C++ 复制代码
    // 自定义比较函数,用于降序排序
    bool compareDescending(int a, int b) {
        return a > b;
    }

class Solution {
public:
    int hIndex(vector<int>& citations) {
        sort(citations.begin(), citations.end(), compareDescending);
        int h = 1;
        int ret = 0;
        for(int i = 0; i < citations.size(); ++i) {
            h = min(i + 1, citations[i]);
            ret = max(h, ret);
        }
        return ret;
    }

};

复杂度分析

时间复杂度: O(nlogN),先使用了sort进行了排序,然后在遍历数组找出答案
空间复杂度: ``O(logN),由于sort的空间复杂度是O(logN)`

方法二:计数排序

解题思路

根据方法一思路我们可以理解为我们将原数组排序后再进行遍历即可,所以我们可以使用计数排序来优化,因为计数排序是一个时间复杂度为线性的排序方法!

这里的思路和方法一略有不同,首先第一个循环内是计数排序的排序过程,第二个循环内从后往前遍历计数排序的数组counter,每次将counteri累加起来,当tot >= i的时候则i为答案。这里的原理可以理解为tot为至少被引用i次的论文数量总和,然后i是被引用次数,当这两个值相交时就为h数。

代码

cpp 复制代码
class Solution {
public:
    int hIndex(vector<int>& citations) {
        int n = citations.size(), tot = 0;
        vector<int> counter(n + 1);
        for (int i = 0; i < n; i++) {
            if (citations[i] >= n) {
                counter[n]++;
            } else {
                counter[citations[i]]++;
            }
        }
        for (int i = n; i >= 0; i--) {
            tot += counter[i];
            if (tot >= i) {
                return i;
            }
        }
        return 0;
    }
};

复杂度分析

时间复杂度: O(N),基于计数排序的时间复杂度为O(N)
空间复杂度: O(N),计数排序的数组的长度为源数组的数据范围

方法三:二分搜索

解题思路

为什么会联想到使用二分搜索?

我们不妨换一个角度思考整个问题,基于方法1的理解我们先将原数组进行了排序,我们将citationsi和i理解为两个函数即:
y 1 = c i t a t i o n s i , y 2 = i y_1=citationsi ,y_2=i y1=citationsi,y2=i

然后这两个函数分别是单调递减和单调递增的,所以如果他们有交点的话那么交点处的citationsi就是h指数(这是大多数情况下),实际实现的情况会有一些额外的情况,例如没有交点那么h指数就是论文个数总和等

代码

cpp 复制代码
class Solution {
public:
    int hIndex(vector<int>& citations) {
        if(citations.size() == 1) return citations[0] >= 1 ? 1 : 0;
        std::sort(citations.begin(), citations.end(),
                  [](int a, int b) { return a > b; });
        int right = citations.size() - 1;
        int left = 0;
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if(mid > citations[mid]) {
                right = mid - 1;
            } else if(mid < citations[mid]) {
                left = mid;
            } else {
                return citations[mid];
            }
        }
        return min(citations[left], left + 1);
    }
};

复杂度分析

时间复杂度: O(nlogN) 排序 + 二分
空间复杂度: O(1),使用了常数个额外的变量

相关推荐
朝朝辞暮i7 分钟前
C++ 第 31C 课:Subscriber 到底是什么
开发语言·c++·算法
杨逢昌工厂6S管理23 分钟前
109-杨逢昌车间管理负熵循环:三环体系持续输出负熵的机制解析
经验分享·笔记·职场和发展·学习方法
Evand J40 分钟前
【MATLAB例程】三维RRT+APF路径规划与AOA-TDOA融合定位算法。附代码的下载链接
算法·matlab·路径规划·rrt·tdoa·apf·aoa
海绵宝宝转agent1 小时前
leetCode100算法开源笔记分享
笔记·算法
写后端的胖头鱼2 小时前
时间复杂度 & 空间复杂度
java·数据结构·算法·时间复杂度·空间复杂度
hahaha60162 小时前
黑体轨迹和色温--光源白点
人工智能·嵌入式硬件·算法·计算机视觉
海绵宝宝转agent2 小时前
基于Redis ZSet+AOP+注解实现限流注解算法
数据库·redis·算法
All for pursuit.3 小时前
【回溯-7】494.目标和
数据结构·c++·算法·leetcode
白杨尚青3 小时前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
Jasmine_llq3 小时前
《P17461 [GESP202609 八级] 生成树计数》
算法·栈·tarjan 算法·边双连通分量·深度优先搜索 dfs·tarjan 保存当前路径节点·模乘法