题目描述
给定一个科研工作者的一系列论文的引用次数(引用次数是非负整数),已经从小到大排好序,请计算他的h因子。
h因子的定义:一个科学家如果有 $h$ 篇文章的引用次数至少是 $h$,并且其他文章的引用次数不超过 $h$,我们就说他的影响因子是 $h$。
注意: 如果一个人有多个可能的 $h$,返回最大的 $h$ 因子。
进一步:
- 这道题目是 LeetCode 274. H-Index的升级版,
citations
保证是严格递增的; - 你能否给出时间复杂度是 $O(logn)$ 级别的算法?
样例
输入:所有文章的引用次数 = [0,1,3,5,6]
输出:3
解释:[0,1,3,5,6] 表示一共有5篇文章,每篇文章分别被引用
0, 1, 3, 5, 6次。由于共有3篇文章的引用次数大于等于3,
且其他两篇文章的引用次数不超过3,所以h因子是3。
算法
(二分) $O(logn)$
由于数组是从小到大排好序的,所以我们的任务是:
在数组中找一个最大的 $h$,使得后 $h$ 个数大于等于 $h$。
我们发现:如果 $h$ 满足,则小于 $h$ 的数都满足;如果 $h$ 不满足,则大于 $h$ 的数都不满足。所以具有二分性质。
直接二分即可。
时间复杂度分析:二分检索,只遍历 $logn$ 个元素,所以时间复杂度是 $O(logn)$。
C++ 代码
class Solution {
public:
int hIndex(vector<int>& citations) {
if (citations.empty()) return 0;
int l = 0, r = citations.size() - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (citations.size() - mid <= citations[mid]) r = mid;
else l = mid + 1;
}
if (citations.size() - l <= citations[l]) return citations.size() - l;
return 0;
}
};
这样写不用特判
请问这道题目使用第二个模板怎么做?
上面题解里是二分出最小的
l
,满足citations.size() - l <= citations[l])
。如果用第二个模板,就先二分出最大的l
, 满足citations.size() - l > citations[l]
,然后在加一。看了录播,那个判断条件还是不太懂,为什么是nums[n-mid]>=mid。因为之前说性质的时候说的是h-1满足该性质,我以为是左半区间是符合要求的,但是最后取的是右半区间。
如果
nums[nums.size() - mid] >= mid
说明至少有mid
篇文章的引用次数大于等于mid
,说明 $h$ 因子至少是mid
,因此最终答案应该在右区间中寻找。为什么这里用不同的模板差别那么大啊,还有最后的特判没看懂
这里用的模板是https://www.acwing.com/blog/content/31/
特判可以避免全0数组之类的情况
全0数组的反例你们第一遍就能想得到吗,我要wa了才知道
有些边界确实比较难考虑到,尽力而为吧
请问我的思路对吗? @yxc
对滴