leetcode274——H指数
- 暴力循环
- 代码分析
- 性能分析
 
- 方法1:排序加线性扫描
- 算法步骤:
 
- 方法2:计数排序(适用于引用次数有上限)
- 算法步骤:
 
 
 

题目链接:leetcode274_H指数
暴力循环
class Solution {
public:int hIndex(vector<int>& citations) {unordered_map<int, int> tmp;for (int i = 1; i <= citations.size(); i++){for (int j = 0; j < citations.size(); j++){if (citations[j] >= i){tmp[i]++;}}if (tmp[i] < i)return i - 1;}return citations.size();}};
代码分析
-  输入参数: - vector<int>& citations:一个整数数组,表示每篇论文的引用次数。
 
-  变量声明: - unordered_map<int, int> tmp:用于存储每个引用次数对应的论文数量。
- int i和- int j:循环变量。
 
-  外层循环: - for (int i = 1; i <= citations.size(); i++):遍历从1到论文总数的所有可能的H指数值。
 
-  内层循环: - for (int j = 0; j < citations.size(); j++):遍历每篇论文的引用次数。
- if (citations[j] >= i):检查当前论文的引用次数是否大于等于当前假设的H指数值i。
- tmp[i]++:如果满足条件,则增加计数器。
 
-  判断条件: - if (tmp[i] < i):如果当前假设的H指数值i对应的论文数量小于i,则返回i-1作为H指数。
 
-  返回值: - 如果所有可能的H指数值都检查完毕,没有找到合适的H指数,则返回论文总数减1。
 
性能分析
- 这段代码的时间复杂度为O(n^2),其中n是论文的数量。这是因为有两个嵌套循环,每个循环都需要遍历整个数组。
- 空间复杂度为O(n),因为使用了一个哈希表来存储每个引用次数对应的论文数量。
改进建议
- 可以通过排序和二分查找来优化算法,将时间复杂度降低到O(n log n)。
- 使用计数排序或桶排序可以进一步优化到O(n)。
根据上述的改进建议,我们可以采取以下两种方法来优化H指数计算算法:
方法1:排序加线性扫描
这个方法的思想是先对引用次数进行排序,然后从高到低遍历排序后的数组,找到最大的i值,使得前i篇论文每篇至少被引用了i次。
算法步骤:
- 对引用次数数组进行降序排序。
- 从头开始遍历排序后的数组,对于每个索引i(从0开始),检查是否满足条件citations[i] >= i+1。
- 如果条件不再满足,则返回当前的i作为H指数。
- 如果遍历结束仍未找到不满足条件的情况,则返回数组长度作为H指数。
时间复杂度:O(n log n),因为排序的时间复杂度为O(n log n)。
空间复杂度:O(1),如果使用原地排序算法的话,不需要额外的空间。
int hIndex(vector<int>& citations) {sort(citations.begin(), citations.end(), greater<int>()); // 按降序排序int i = 0;for (; i < citations.size() && citations[i] > i; ++i);return i;
}
方法2:计数排序(适用于引用次数有上限)
如果引用次数有一个合理的上限,比如不超过论文总数或某个固定的最大值,我们可以用计数排序来实现更高效的算法。该方法特别适合于引用次数不是非常大的情况。
算法步骤:
- 创建一个大小为n+1的数组counts用于计数,其中n是论文数量。
- 遍历citations数组,对于每个引用次数c,如果c大于等于n,则在counts[n]中增加计数;否则,在counts[c]中增加计数。
- 从后往前遍历counts数组,累计论文数量total,直到total大于等于当前索引i,此时i即为H指数。
时间复杂度:O(n),因为我们只需要遍历一次citations和一次counts。
空间复杂度:O(n),需要额外的counts数组。
int hIndex(vector<int>& citations) {int n = citations.size();vector<int> counts(n + 1, 0);// 计算每个引用次数出现的频次for (int c : citations)counts[min(c, n)]++;// 从高往低累积论文数量,寻找H指数int total = 0;for (int i = n; i >= 0; --i) {total += counts[i];if (total >= i)return i;}return 0;
}
这两种方法都可以有效地减少原始代码中的冗余计算,并且提高了时间效率。