lc经典面试经典150题之数组/字符串篇(持续更新中)

11.H指数

标签

排序 数组 计数排序

题目描述

  给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。
  根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。

原题链接 H指数

解法一:排序

  使用普通排序算法降序排序,只要当前的文章引用次数大于当前的h指数(H指数从零开始)即可;

	public int hIndex(int[] citations) {
        //当前文章被引用次数
        int currentArticleIndex=0;
        //h指数,初始时认为当前发表了h个论文,并且至少有h个论文的引用次数大于等于h;
        int h=0;
        //对数组进行排序
        Arrays.sort(citations);
        //反转数组
        reverse(citations,0,citations.length-1);
        //遍历从高到低
        for (;currentArticleIndex<citations.length;currentArticleIndex++){
            //表示已经有一篇论文的引用次数超过0了;
            if(citations[currentArticleIndex]>h){
                h++;
            }
        }
        return h;
    }
    
	public void reverse(int[] arr,int left,int right){
        while (left<right){
            int t=arr[left];
            arr[left]=arr[right];
            arr[right]=t;
            left++;
            right--;
        }
    }

解法二:计数排序

由于解法一中最终的时间复杂度和排序算法有关,因此可以优化排序算法为计数排序,计数排序具有线性的时间复杂度;

什么是计数排序

计数排序属于典型的用空间换时间的算法;对于一个随机的数组比如是:arr=[2,4,1,2,5,3,4,8,7];

  • 计算最该数组中的最大值和最小值o(n);
  • 根据最大值和最小值设定计数数组的长度;
  • 计数数组,表示各个数字出现的次数,将各个数字作为下标存入计数数组,对应的值为该数字出现的次数,比如c=[0,1,2,1,2,1,0,1,1];
  • 累加数组,下标对应的元素的值表示小于等于该元素的数字的个数,比如对于上一步中c=[0,1,2,1,2,1,0,1,1],那么d=[0,1,3,4,6,7,7,8,9];计算方式就是第一个位置不变(因为小于等于该元素的只有他自己,他自己就是最小值),从第二个位置开始,每个下标(元素)的值等于上一个下标对应值加上自己的值;
  • 分配,按照原始数组arr中的顺序,该元素对应的位置就是累加数组中当前元素下标的值-1就是排序后的该元素的数组下标,并且每分配一次,都将累加数组中对应下标元素的值减一;
/**
 * 计数排序
 */
public class CounterSort {
    //计数排序
    public int[] counterSort(int[] arr){
        int maxValue=selectMax(arr);
        int minValue=selectMin(arr);
        if(minValue<0){
            //如果最小值小于零,使用偏移量将所有元素移动到0以上;偏移量为minValue的绝对值
            for (int i=0;i<arr.length;i++) {
                arr[i] += Math.abs(minValue);
            }
        }
        //获取计数数组
        int[] counterArray=counterArray(arr);
        //直接获取累加数组
        int[] accumulationArray = accumulationArray(counterArray);
        //新数组
        int[] newArray=new int[arr.length];
        //进行分配
        for (int i=0;i<arr.length;i++){
            //计算下标
            int index=accumulationArray[arr[i]]-1;
            newArray[index]=arr[i];
            //分配之后减一
            accumulationArray[arr[i]]--;
        }
        return newArray;
    }

    //获得最大值
    public int selectMax(int[] arr){
        int maxValue=Integer.MIN_VALUE;
        for(int i=0;i<arr.length;i++){
            if(arr[i]>maxValue) maxValue=arr[i];
        }
        return maxValue;
    }

    //获得最小值
    public int selectMin(int[] arr){
        int minValue=Integer.MAX_VALUE;
        for(int i=0;i<arr.length;i++){
            if(arr[i]<minValue) minValue=arr[i];
        }
        return minValue;
    }

    //返回计数数组
    public int[] counterArray(int[] arr){
        int maxValue=selectMax(arr);
        int[] counterArr=new int[maxValue+1];
        for (int i=0;i<arr.length;i++){
            counterArr[arr[i]]++;
        }
        return counterArr;
    }

    //返回累加数组
    public int[] accumulationArray(int[] counterArray){
        int[] accumulationArray=counterArray;
        for (int i=1;i<counterArray.length;i++){
            accumulationArray[i]+=accumulationArray[i-1];
        }
        return accumulationArray;
    }

}

调试代码

public class CounterTest {
    public static void main(String[] args) {
        CounterSort counterSort=new CounterSort();
        int[] arr={2,4,1,2,5,3,4,8,7};
        int[] sort = counterSort.counterSort(arr);
        System.out.println("排序后结果:"+ Arrays.toString(sort));
    }
}

使用计数排序解决H指数的问题
代码同上,只需要把排序的部分改成自定义的计数排序就行了.

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黒猫.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值