解法一、数组记录,下标为次数,数据为篇数
首先是题目问题简化。由于是至少,获取了从高下标往低遍历的信息。一次遍历,进行数据处理,也就是键值对的思路转换。从citations的论文(下标)-引用数(数据),转变为 引用数(下标)-达引用数篇数(数据),随即遍历即可。
新开了等长度的arr。这里学到了昨天的数据处理方式,0不必记(也为了防止越界),高于len的不必考虑,因为h指数受两个约束,最大就是论文篇数(即len)。
class Solution {
public static int hIndex(int[] citations) {
int len = citations.length;
int[] arr = new int[len];//下标+1是对应的数量,里面存储到达该数量的论文数
for(int i = 0;i < len;i++){
if(citations[i] > 0){
if(citations[i] > len){
citations[i] = len;
}
arr[citations[i] - 1]++;
}
}
int sum = 0;
for(int i = len-1;i >= 0;i--){//从高往低遍历
sum += arr[i];
if(sum >= i + 1){
return i+1;
}
}
return 0;//边界处理
}
}
解法二、排序
猜想因为该题各论文间意义等同,所以打乱下标也没关系,最重要的是引用频率。如[1,5,3,2]排序后[1,2,3,5],x是引用数,y是下标(这里有了排序意义,也就成为了篇数)。引用数越来越大,篇数越来越小。从下往上遍历,若是引用频率大于或等于篇数,返回里面大概率较小的篇数。
class Solution {
public int hIndex(int[] citations) {
Arrays.sort(citations);
int max = 0;
for (int i = 0; i < citations.length; i++) {
if (citations[i] == 0) {
continue;
}
int x = citations[i];
int y = citations.length - i;
if (x >= y) {
max = Math.max(max, y);
}
}
return max;
}
}
解法三、二分查找
这个稍微反应了一下···后来发现h指数在[0,N]之间,所以二分的区间是这个区间。空间复杂度很低,时间复杂度和解法二的sort一样是nlogn
确实查找某个特定的、单独的数可以引入二分。
class Solution {
public int hIndex(int[] citations) {
int left=0,right=citations.length;
int mid=0,cnt=0;
while(left<right){
// +1 防止死循环
mid=(left+right+1)>>1;
cnt=0;
for(int i=0;i<citations.length;i++){
if(citations[i]>=mid){
cnt++;
}
}
if(cnt>=mid){
// 要找的答案在 [mid,right] 区间内
left=mid;
}else{
// 要找的答案在 [0,mid) 区间内
right=mid-1;
}
}
return left;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/h-index/solutions/869042/h-zhi-shu-by-leetcode-solution-fnhl/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
碎碎念
- 二分原来排序要求这么灵活···看到解法的第一反应是这个,后来发现这里是有自成的一个秩序的,不一定数组必须排序。
- 虽然这次没有用上原地哈希,但是灵活度相近。
新手期成长确实还算挺速度的···没想到mid题会写这么快,正反馈很大,感觉压力不是那么大了