题目
标题和出处
标题:H 指数
出处:274. H 指数
难度
5 级
题目描述
要求
给定一个整数数组 citations \texttt{citations} citations,其中 citations[i] \texttt{citations[i]} citations[i] 表示研究者的第 i \texttt{i} i 篇论文被引用的次数,计算并返回该研究者的 h 指数。
根据 h 指数的定义,一名科研人员的 h 指数是指其发表的 n \texttt{n} n 篇论文中总共有 h \texttt{h} h 篇论文分别被引用了至少 h \texttt{h} h 次,且其余的 n − h \texttt{n} - \texttt{h} n−h 篇论文每篇被引用次数不超过 h \texttt{h} h 次。
如果 h \texttt{h} h 有多种可能的值,其中最大的值作为 h 指数。
示例
示例 1:
输入:
citations
=
[3,0,6,1,5]
\texttt{citations = [3,0,6,1,5]}
citations = [3,0,6,1,5]
输出:
3
\texttt{3}
3
解释:
[3,0,6,1,5]
\texttt{[3,0,6,1,5]}
[3,0,6,1,5] 表示研究者总共有
5
\texttt{5}
5 篇论文,每篇论文相应的被引用了
3,
0,
6,
1,
5
\texttt{3, 0, 6, 1, 5}
3, 0, 6, 1, 5 次。
由于研究者有
3
\texttt{3}
3 篇论文每篇至少被引用了
3
\texttt{3}
3 次,其余
2
\texttt{2}
2 篇论文每篇被引用不多于
3
\texttt{3}
3 次,所以 h 指数是
3
\texttt{3}
3。
示例 2:
输入:
citations
=
[1,3,1]
\texttt{citations = [1,3,1]}
citations = [1,3,1]
输出:
1
\texttt{1}
1
数据范围
- n = citations.length \texttt{n} = \texttt{citations.length} n=citations.length
- 1 ≤ n ≤ 5000 \texttt{1} \le \texttt{n} \le \texttt{5000} 1≤n≤5000
- 0 ≤ citations[i] ≤ 1000 \texttt{0} \le \texttt{citations[i]} \le \texttt{1000} 0≤citations[i]≤1000
解法一
思路和算法
首先将数组 citations \textit{citations} citations 排序,然后按照从大到小的顺序遍历数组 citations \textit{citations} citations,计算 h 指数。
根据 h 指数的定义,如果已经遍历的 j j j 个元素都大于等于 j j j,则 h 指数至少为 j j j。其中最大的 j j j 的值即为 h 指数。
代码
class Solution {
public int hIndex(int[] citations) {
Arrays.sort(citations);
int h = 0;
for (int i = citations.length - 1, j = 1; i >= 0 && citations[i] >= j; i--, j++) {
h = j;
}
return h;
}
}
复杂度分析
-
时间复杂度: O ( n log n ) O(n \log n) O(nlogn),其中 n n n 是数组 citations \textit{citations} citations 的长度。排序需要 O ( n log n ) O(n \log n) O(nlogn) 的时间,从大到小遍历数组需要 O ( n ) O(n) O(n) 的时间,时间复杂度是 O ( n log n ) O(n \log n) O(nlogn)。
-
空间复杂度: O ( log n ) O(\log n) O(logn),其中 n n n 是数组 citations \textit{citations} citations 的长度。排序需要 O ( log n ) O(\log n) O(logn) 的递归调用栈空间。
解法二
思路和算法
解法一需要 O ( n log n ) O(n \log n) O(nlogn) 的时间复杂度。如果使用计数代替排序,则可以降低时间复杂度。
根据 h 指数的定义,h 指数不可能超过论文总数,即如果将数组 citations \textit{citations} citations 中的大于数组长度 n n n 的元素都改成 n n n,不会改变 h 指数的结果。为了方便计算,计数时将每篇论文被引用的次数限制在范围 [ 0 , n ] [0, n] [0,n] 内,大于 n n n 的引用次数都按照 n n n 次引用计算。
得到计数之后,反向遍历计数数组,同时维护已经遍历的论文总数 sum \textit{sum} sum。当遍历到计数数组的下标 i i i 时, sum \textit{sum} sum 表示被引用至少 i i i 次的论文总数,如果 i ≥ sum i \ge \textit{sum} i≥sum,则 i i i 就是符合要求的 h 指数值。由于 h 指数值应该取可能的最大值,因此第一个使 i ≥ sum i \ge \textit{sum} i≥sum 的 i i i 即为 h 指数值。
代码
class Solution {
public int hIndex(int[] citations) {
int n = citations.length;
int[] counts = new int[n + 1];
for (int citation : citations) {
counts[Math.min(citation, n)]++;
}
int h = 0, sum = 0;
for (int i = n; i >= 0; i--) {
sum += counts[i];
if (sum >= i) {
h = i;
break;
}
}
return h;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 citations \textit{citations} citations 的长度。遍历数组 citations \textit{citations} citations 计数和遍历计数数组都需要 O ( n ) O(n) O(n) 的时间。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 citations \textit{citations} citations 的长度。计数需要 O ( n ) O(n) O(n) 的空间。