H指数(H-index)是衡量学者科研产出的重要指标,由物理学家Jorge Hirsch在2005年提出。这个概念后来被引入算法领域,成为一道经典的数组处理题目。题目描述很简单:给定一位研究者论文的被引用次数数组,要求计算其H指数。
H指数的定义是:科学家有h篇论文至少被引用h次,且其他N-h篇论文每篇被引用次数不超过h次。举个例子,如果某学者的论文引用次数是[3,0,6,1,5],那么将其降序排列后得到[6,5,3,1,0],可以看到第3篇论文引用次数为3,而第4篇只有1次,因此H指数为3。
这个指标巧妙地将数量和质量结合在一起——既要求有一定数量的论文,又要求这些论文达到一定的引用水平。在实际科研评价中,H指数比单纯的总引用数或发文量更能全面反映学者的影响力。
最直观的解法是从高到低枚举可能的h值,直到找到满足条件的最大值。具体步骤:
这种方法时间复杂度为O(n²),因为最坏情况下需要检查n个可能的h值,每次检查需要O(n)时间。虽然逻辑简单,但在力扣上提交会导致超时。
观察到排序后的数组具有单调性,我们可以优化检查过程:
这种解法将时间复杂度降到了O(nlogn),主要由排序步骤决定。空间复杂度为O(1)(如果允许修改原数组)或O(n)(如果需要额外空间)。
提示:在实际编码时要注意边界条件,特别是所有论文引用次数都大于论文数量的情况,此时H指数应为n。
对于引用次数可能很大的情况,我们可以使用计数排序的思想:
这种方法巧妙地将问题转化为前缀和问题,时间复杂度优化到了O(n),但需要额外的O(n)空间。对于n较大的情况,这种解法优势明显。
python复制def hIndex(citations):
citations.sort(reverse=True)
for i, cite in enumerate(citations):
if cite < i + 1:
return i
return len(citations)
关键点说明:
reverse=True确保降序排列enumerate同时获取索引和值i+1表示当前潜在的h值(因为i从0开始)python复制def hIndex(citations):
n = len(citations)
count = [0] * (n + 1)
# 统计各引用次数出现的频率
for cite in citations:
if cite >= n:
count[n] += 1
else:
count[cite] += 1
# 从后向前累加
total = 0
for i in range(n, -1, -1):
total += count[i]
if total >= i:
return i
return 0
实现细节:
total >= i时立即返回,保证是最大h值设计测试用例时应考虑:
例如:
python复制test_cases = [
([], 0),
([0], 0),
([1], 1),
([100], 1),
([3,0,6,1,5], 3),
([1,2,3,4,5], 3),
([5,5,5,5,5], 5),
([0,0,0,0,0], 0)
]
在实际应用中,选择哪种算法取决于数据特点:
例如H指数II的二分查找解法:
python复制def hIndex(citations):
left, right = 0, len(citations)
while left < right:
mid = (left + right) // 2
if citations[mid] >= len(citations) - mid:
right = mid
else:
left = mid + 1
return len(citations) - left
H指数算法虽然源于学术评价,但其核心思想可以应用于许多场景:
在工程实现时还需要考虑:
我曾在用户影响力评估系统中应用过类似的算法,发现当数据量达到百万级时,计数排序法的优势非常明显,比传统排序法快10倍以上。但要注意内存消耗,必要时可以采用分桶策略。