Medium

题目描述

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

根据维基百科上 h 指数 的定义:h 指数是能够同时满足下述两个条件的最大值 h

  • 该研究者至少有 h 篇论文分别被引用了至少 h 次。
  • 其余的 N - h 篇论文每篇被引用次数 不超过 h 次。

示例 1:

输入:citations = [3,0,6,1,5]
输出:3
解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
     由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。

示例 2:

输入:citations = [1,3,1]
输出:1

提示:

  • n == citations.length
  • 1 <= n <= 5000
  • 0 <= citations[i] <= 1000

解题思路

这道题要找到最大的 h 值,使得至少有 h 篇论文被引用了至少 h 次。

方法一:排序法 将引用次数从大到小排序,然后遍历数组。对于第 i 篇论文(从0开始),如果 citations[i] >= i+1,说明至少有 i+1 篇论文被引用了至少 i+1 次。我们要找的是满足条件的最大值。

方法二:计数排序法(推荐) 由于 h 指数的最大值不会超过论文总数 n,我们可以用计数数组统计每个引用次数的论文数量。然后从高到低累计,找到第一个满足"至少有 h 篇论文被引用至少 h 次"的位置。

计数排序法的优势是时间复杂度更优,特别适合这道题的数据范围。我们创建一个大小为 n+1 的数组,将所有大于等于 n 的引用次数都计入 bucket[n] 中(因为 h 指数最大就是 n)。

算法步骤:

  1. 创建计数数组,统计各引用次数的论文数量
  2. 从后往前累计,计算至少被引用 i 次的论文总数
  3. 找到最大的 h,使得至少有 h 篇论文被引用至少 h 次

代码实现

class Solution {
public:
    int hIndex(vector<int>& citations) {
        int n = citations.size();
        vector<int> bucket(n + 1, 0);
        
        // 计数:统计每个引用次数的论文数量
        for (int citation : citations) {
            if (citation >= n) {
                bucket[n]++;
            } else {
                bucket[citation]++;
            }
        }
        
        // 从后往前累计,找到h指数
        int count = 0;
        for (int i = n; i >= 0; i--) {
            count += bucket[i];
            if (count >= i) {
                return i;
            }
        }
        return 0;
    }
};
class Solution:
    def hIndex(self, citations: List[int]) -> int:
        n = len(citations)
        bucket = [0] * (n + 1)
        
        # 计数:统计每个引用次数的论文数量
        for citation in citations:
            if citation >= n:
                bucket[n] += 1
            else:
                bucket[citation] += 1
        
        # 从后往前累计,找到h指数
        count = 0
        for i in range(n, -1, -1):
            count += bucket[i]
            if count >= i:
                return i
        return 0
public class Solution {
    public int HIndex(int[] citations) {
        int n = citations.Length;
        int[] bucket = new int[n + 1];
        
        // 计数:统计每个引用次数的论文数量
        foreach (int citation in citations) {
            if (citation >= n) {
                bucket[n]++;
            } else {
                bucket[citation]++;
            }
        }
        
        // 从后往前累计,找到h指数
        int count = 0;
        for (int i = n; i >= 0; i--) {
            count += bucket[i];
            if (count >= i) {
                return i;
            }
        }
        return 0;
    }
}
var hIndex = function(citations) {
    const n = citations.length;
    const bucket = new Array(n + 1).fill(0);
    
    // 计数:统计每个引用次数的论文数量
    for (const citation of citations) {
        if (citation >= n) {
            bucket[n]++;
        } else {
            bucket[citation]++;
        }
    }
    
    // 从后往前累计,找到h指数
    let count = 0;
    for (let i = n; i >= 0; i--) {
        count += bucket[i];
        if (count >= i) {
            return i;
        }
    }
    return 0;
};

复杂度分析

复杂度计数排序法排序法
时间复杂度O(n)O(n log n)
空间复杂度O(n)O(1)

相关题目