T274-H指数
T274
整数数组 citations
,其中 citations[i]
表示研究者的第 i
篇论文被引用的次数。计算并返回该研究者的 h
指数。
h 指数的定义:h
代表“高引用次数” ,一名科研人员的 h
指数 是指他(她)至少发表了 h
篇论文,并且 至少 有 h
篇论文被引用次数大于等于 h
。如果 h
有多种可能的值,h
指数 是其中最大的那个。
示例 1:
1 | 输入:citations = [3,0,6,1,5] |
示例 2:
1 | 输入:citations = [1,3,1] |
分析一下,根据定义,我们可以从中读出什么?
n = citations.size
是研究者的论文总数目h
的范围是0
到n
- 结果与
citations[i]
中元素顺序无关,意味着可以排序
让我们先把复杂度抛到一边,写出一个硬解,感受一下。 由于提到了“至少 有 h
篇论文被引用次数大于等于 h
”,可以联想到"y=x
"这种直线对可行域进行划分。简单思考后可以写出这样的代码:
1 | fun hIndex(citations: IntArray): Int { |
首先,对传入的 citations
数组进行降序排序。这样排序后,索引 i
处的值 citations[i]
表示至少被引用了 citations[i]
次的论文数量。
ans
指的是计算得到的H指数,初始化为0。
开始循环,citations[ans] > ans
表示当前论文引用次数大于 ans
,这意味着至少有 ans
篇论文被引用了 ans
次以上。循环递增 ans
的值,直到找到最大的 ans
满足条件,即 citations[ans] <= ans
为止。
将论文的引用次数进行排序,然后从最大的引用次数开始逐步减小,找到最大的 ans
满足 citations[ans] <= ans
的条件,即为H指数
这里用到了排序,时间复杂度是O(logN)
,有没有办法把复杂度降低到O(N)
?去掉排序,我们不妨用空间换时间,用另一个数组count[i]
存储论文的被引用次数。具体含义是,count[i]=a
表示的是被引用i
次的论文一共有a
篇。那这个数组中最大的下标就是citations[i]
中最大的元素值:citations.max()
。
1 | fun hIndex(citations: IntArray):Int{ |
total
用于累计被引用次数大于等于当前检查的引用次数的论文数量。
使用逆序的 for
循环,从 countSize - 1
(即数组最后一个索引)开始向前遍历 count
数组。
在每一次迭代中,将 total
增加 count[n]
,表示将当前引用次数为 n
的论文数量加入到 total
中。
然后检查 total
是否大于等于 n
,如果满足,则说明找到了H指数,即 n
,直接返回 n
。
如果循环结束后仍未找到符合条件的 n
,则返回 -1
,表示未找到合适的H指数。
这样,复杂度降低到了O(N)
。
当然,作为Kotlin
的使用者,你还可以写的更加优雅:
1 | fun hIndex(citations: IntArray): Int { |