题目
给你一个整数数组 citations
,其中 citations[i]
表示研究者的第 i
篇论文被引用的次数。计算并返回该研究者的 h
指数。
根据维基百科上 h 指数的定义:h
代表“高引用次数” ,一名科研人员的 h
指数 是指他(她)至少发表了 h
篇论文,并且 至少 有 h
篇论文被引用次数大于等于 h
。如果 h
有多种可能的值,h
指数 是其中最大的那个。
示例 1:
输入:citations = [3,0,6,1,5]
输出:3
解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。
示例 2:
输入:citations = [1,3,1]
输出:1
解
①穷举法,用时太久,24ms
class Solution {
public int hIndex(int[] citations) {
int max_h=citations.length;
int search=citations.length/2+1;
int h=0;
for(int i=0;i<max_h;i++){
int count=0;
for(int j=0;j<max_h;j++){
if(citations[j]>=search){
count++;
}
}
if(count>=search){
h=search;
search++;
}
else{
search--;
}
}
return h;
}
}
②二分法,设置了h的范围,range1是下限,range2是上限,不断更新上下限,每次和范围中间值比较,对只有一个元素的特殊情况单独处理
class Solution {
public int hIndex(int[] citations) {
int h_range1=0,h_range2=citations.length;
int h=0;
if(h_range2-h_range1<=1){
// 对于只有一个元素的特殊处理
if(citations[0]==0)return 0;
h=h_range2-h_range1;
return h;
}
for(int i=0;i<citations.length;i++){
int count=0;
int search;
if((h_range1+h_range2)%2==0){
search=(h_range1+h_range2)/2;
}
else{
search=(h_range1+h_range2)/2+1;
}
for(int j=0;j<citations.length;j++){
if(citations[j]>=search){
count++;
}
}
if(count>=search){
if(h_range1==search)break;//如果下限不再变化就结束
h=search;
h_range1=search;
}
else{
if(h_range2==search)break;//如果上限不再变化就结束
h_range2=search;
}
if(h_range2==h_range1)break;
}
return h;
}
}
③二分法的改进版本
上一个二分法写的比较复杂,下面是别人的二分法
class Solution {
public int hIndex(int[] citations) {
int n=citations.length;
int l=0,r=n;
while(l<r){
int mid=(l+r+1)>>1;//右移符号相当于除法
int count=0;
for(int i:citations) if(i>=mid) count++;
if(count>=mid) l=mid;
else r=mid-1;//-1是因为mid本身就是不满足的情况,所以无需放在这个范围内
}
return r;//r==l
}
}