Given an array of citations (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index.
According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each."
For example, given citations = [3, 0, 6, 1, 5]
, which means the researcher has 5
papers in total and each of them had received 3, 0, 6, 1, 5
citations respectively. Since the researcher has 3
papers with at least 3
citations each and the remaining two with no more than 3
citations each, his h-index is 3
.
Note: If there are several possible values for h
, the maximum one is taken as the h-index.
算法一,排序
hIndex定义为,有h篇文章,每篇被引用的次数至少为h;且求一个h的最大值。则为hIndex。
为了方便比较,此处进行的是降序排列。
class Solution {
public:
int hIndex(vector<int>& citations) {
sort(citations.rbegin(), citations.rend());
int index = 0;
while (index < citations.size() && citations[index] > index)
++index;
return index;
}
};
算法二,O(n)
算法一,需要进行排序,所以时间复杂度为O(nlogn)。
hIndex的取值范围为 [0, citataions.size()]。
引入额外存储空间,count[i], 下标表示文章的引用次数,数组元素值为达到该引用次数的文章数量。
1. 第一趟扫描完成count数组的统计
2. 第二趟从后向前扫描count数组,并从后向前进行累加,以得出引用次数超过 i 值的文章数量,如果文章数量>= i,则满足hIndex定义。
class Solution {
public:
int hIndex(vector<int>& citations) {
const int M = citations.size();
vector<int> count(M+2);
for (auto c: citations)
++count[c>M ? M : c];
for (int i=M; i>=0; i--) {
count[i] += count[i+1];
if (count[i] >= i)
return i;
}
return 0;
}
};
算法三,分区
使用快速排序的划分方法。
1. 选取一个枢轴,将小于枢柚的值聚合到左边,大于等于其值聚合到右边。
2. 如果右区间宽度小于或者等于枢轴,则说明hIndex值至少是右区间宽度。
此时,继续在左区间进行再次划分,以寻找最大的hIndex值
3. 如果右区间宽度>枢轴,则不满足hIndex定义。在右区间继续进行划分。
4. 直到区间为空。
leetcode上实际执行时间为4ms。
class Solution {
public:
int hIndex(vector<int>& citations) {
const int M = citations.size();
int hindex = 0;
int start = 0, stop = M-1;
while (start <= stop) {
auto pivot = partition(citations, start, stop);
if (M - pivot <= citations[pivot]) {
hindex = M - pivot;
stop = pivot - 1;
}
else
start = pivot + 1;
}
return hindex;
}
int partition(vector<int>& citations, int start, int stop) {
const auto pivot = citations[stop];
for (auto i=start; i<stop; i++) {
if (citations[i] < pivot)
swap(citations[i], citations[start++]);
}
swap(citations[start], citations[stop]);
return start;
}
};