排序题目:H 指数
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法一
- 思路和算法
- 代码
- 复杂度分析
- 解法二
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题: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) 的空间。