leetcode面试经典150题——11H 指数

题目: H 指数

描述
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 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。

方法一:枚举法(暴力法)
H指数为n的意义,表示在发表的论文中至少有n篇被引用的次数大于或者等于n,所以最简单的暴力法就是从H=1开始找,直到找到H=n,也就是在数组中寻找n个大于等于n的数字
时间复杂度为o(n²)
空间复杂度为o(1)

int hIndex(vector<int>& citations) {
	//H要等于n,那么数组里面就要有n个大于等于n的数字
	int n = citations.size();
	int H = 0;
	for(int i=1;i<=n;i++){//优化:i的最大值应该为数组中的最大值和数组的长度n中的最小的一个
		int count = 0;
		for(int j=0;j<n;j++){
			if(citations[j]>=i){
				count++;
			} 
			if(count>=i){//满足H=i的条件时,跳出循环,继续求下一个H
				H = i;
				break;
			}
		}
	}
	return H; 
}

方法二:我们可以先对元素进行降序排序,排好之后从头开始遍历,遍历到citations[i]的时候,前面是有i个元素>=当前元素的,所以一共有i+1个元素>=citations[i],所以我们只需要判断citations[i]是否大于等于i+1,从而判断H指数,而i从0开始,所以我们可以找出所有H(1-n)的情况
排序为快速排序,时间复杂度为o(nlogn),后面只需遍历一遍数组,总的时间复杂度为:o(nlogn)
快速排序的空间复杂度为o(logn)

int hIndex(vector<int>& citations) {
	sort(citations.begin(),citations.end(),greater<int>());//降序排序 
	//第i个元素前面有i个元素是大于等与citations[i]的 
	int n = citations.size();
	int H = 0;
	for(int i=0;i<n;i++){
		if(citations[i]>=i+1){//加上当前元素一共有i+1个>=citations[i]的 
			H = i+1; 
		} 
	}
	return H; 
}

方法三:计数排序,由方法二可知,我们时间复杂度主要由排序算法决定,那么我们考虑用计数排序来进行优化,申请一个长度为n+1的数组nums,nums[i]表示论文被引用次数为i的论文篇数,由于H指数不可能超过n,那么对应被引用次数大于n的论文,我们存储到nums[n]中,最后从后往前遍历nums,记录被引用次数>=i的论文总数,然后判断是否>=i,从而得出H的值.
此方法为典型的空间换时间算法
时间复杂度o(n)
空间复杂度o(n)

int hIndex(vector<int>& citations) {
	int n = citations.size();
	vector<int> nums(n+1);//维护一个长度为n+1的数组
	for(int i = 0;i<n;i++){
		//记录被引用次数为i的论文的篇数 
		if(citations[i]>=n){
			nums[n]++;
		}else{
			nums[citations[i]]++;
		}
	}
	int sum = 0;
	for(int i=n;i>=0;i--){
		sum+=nums[i];//求被引用次数不少于i的论文总数
		if(sum>=i){
			return i;//H指数
		}
	} 
	return 0;
}

你可能感兴趣的:(leetcode,面试,算法)