当前位置: 首页 > news >正文

面试经典算法150题系列-h指数

h指数

给你一个整数数组 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

实现思路:

要计算一个研究者的 h 指数,你可以按照以下步骤进行:

  1. 排序:将论文引用次数从高到低进行排序。

  2. 计算 h 指数:从排序后的数组的最后一个元素(即引用次数最高的论文)开始,向前遍历数组:

    • 维护一个计数器 h,初始值为 1。
    • 对于数组中的每个元素 citations[i]
      • 如果 citations[i] 大于或等于 h,则 h 加 1。
      • 如果 citations[i] 小于 h,则停止增加 h,因为此时已经不能满足 h 指数的定义(即每篇论文至少被引用 h 次)。
  3. 返回 h 指数:返回计算出的 h 值。

思路模拟:以citations = [3,0,6,1,5]为例(大家可以在图纸上画一遍模拟一下)

首先我们进行从高到低排序得到 6,5,3,1,0.然后从数组最后往前开始遍历数组。判断citations[i]是否大于等于h

第一次遍历:0 (数组元素)< 1(h的值),因此不满足条件,结束当前遍历。

第二次遍历:1 = 1,满足条件,h++,进行下一次遍历。

第三次遍历:3 > 2 满足条件,h++,进行下一次遍历。

第四次遍历:5 > 3 满足条件,h++,进行下一次遍历。

第五次遍历: 6 > 4 满足条件,h++,循环结束。

然后因为我们h是从1开始,最后一次满足条件时多加了一次,在我们返回时则需要减1.

实现代码:

public  int hIndex(int[] citations) {//数组从高到低进行排序  Arrays.sort函数Arrays.sort(citations);int h=1;  //定义h指数//对数组进行遍历,从后往前,如果数组元素大于等于h,则为h指数,h++for (int i = citations.length-1; i >=0 ; i--) {if (citations[i] >= h){h++;}else {break;}}return h-1;//因最后一次符合条件的判断多加了一次,因此需要减一}

实现思路二:使用一个计数数组来统计每个引用次数的论文数量,然后通过反向迭代来确定 h 指数。

实现代码:

public int hIndex(int[] citations) {int n = citations.length; // 1. 获取输入数组 citations 的长度。int[] count = new int[n + 1]; // 2. 创建一个长度为 n + 1 的数组 count,用于统计每个引用次数的论文数量。数组索引从 0 到 n,其中索引 i 表示引用次数为 (i + 1) 的论文数量。for (int num : citations) { // 3. 遍历数组 citations 中的每个引用次数 num。count[Math.min(num, n)]++; // 4. 对于每个引用次数 num,如果 num 大于 n,则它将与 n 一样被视为 n。然后,对应索引的 count 数值增加 1。}int total = 0; // 5. 初始化总论文数量计数器 total 为 0,用于计算至少被引用特定次数的论文总数。for (int i = n; ; i--) { // 6. 开始一个无限循环,从 n 开始递减至 0。循环条件为空,表示无限迭代,但内部的逻辑将决定何时退出循环。total += count[i]; // 7. 将当前索引 i 对应的引用次数的论文数量加到 total 上。这表示统计了至少被引用 i 次的论文数量。if (total >= i) { // 8. 如果 total 大于等于当前的索引 i,根据 h 指数的定义,我们找到了满足条件的最小 h 值。return i; // 9. 返回索引 i 作为 h 指数的值。此时,我们知道至少有 i 篇论文被引用了至少 i 次。}}
}

代码逻辑的核心在于:

  • 使用 count 数组来统计每个引用次数的论文数量,数组索引 i 表示引用次数为 (i + 1) 的论文数量。
  • 通过反向迭代 count 数组,累加至少被引用特定次数的论文总数。
  • 当累加的论文总数 total 大于等于当前的引用次数 i 时,满足 h 指数的定义,返回当前的 i 作为 h 指数。

这种方法的时间复杂度是 O(n),其中 n 是数组 citations 的长度,因为它只需要对数组进行两次遍历:一次用于统计引用次数,一次用于计算 h 指数。这种方法避免了对原始数组进行排序,因此在某些情况下可能更高效。

知识补充:

1.Arrays.sort()函数

Arrays.sort() 是 Java 中的一个方法调用,用于对整数数组 进行排序。这个方法是基于 TimSort 算法实现的,TimSort 是一种结合了归并排序和插入排序的高效排序算法,它在多种情况下都能提供很好的性能。(关于归并排序和插入排序如果有需要,后期我出两期内容)

以下是关于 Arrays.sort() 方法的一些关键点:

  1. 原地排序Arrays.sort() 对数组进行原地排序,意味着它直接修改传入的数组,而不是创建一个新的排序数组。

  2. 时间复杂度:对于大多数情况,Arrays.sort() 的平均时间复杂度是 O(n log n),其中 n 是数组的长度。

  3. 稳定性Arrays.sort() 是一个稳定的排序算法,这意味着相等的元素在排序后保持它们原始的顺序。

  4. 使用场景:当你需要对数组中的元素进行排序时,可以使用这个方法。例如,你可以对整数、浮点数、对象数组等进行排序。

  5. 重载方法Arrays.sort() 提供了多个重载版本,支持不同类型的数组排序,包括原始数据类型数组(如 int、float 等)和对象数组。

  6. 自定义排序:对于对象数组,你可以传递一个 Comparator 实例作为参数,以自定义排序逻辑。

  7. 并行排序:从 Java 8 开始,Arrays.sort() 默认使用并行排序(如果底层的硬件支持),这可以提高大数据集的排序速度。

  8. 异常处理:如果数组包含 null 或排序器(Comparator)抛出异常,则 Arrays.sort() 会抛出 NullPointerException 或其他相关异常。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Jenkins参数化构建
  • C# 使用 NLog 输出日志到文件夹
  • springboot新农村综合展示平台-计算机毕业设计源码41793
  • 震惊!一男子深夜燥热难耐,竟然偷偷起身打开电脑并开始 学习c++入门基础(下)
  • 一个很变态却非常实用的发论文的新方向,【Transformer+目标检测】
  • 为什么有的地方笔记本经常连不上wifi,而手机可以?
  • Linux学习第56天:RGB转HDMI
  • Radiant Photo 1.4.1 AI智能完美照片修图插件支持PS ai beta
  • 珠海市举办“数智赋能产业转型与创新培训专场”活动
  • 【天机学堂】面试总结
  • 繁简之争:为什么手机芯片都是 ARM
  • 【Material-UI】Autocomplete 组件的局限性(Limitations)详解
  • [最短路SPFA]--启动!!!!!
  • 微信小程序开发优惠券制作源码
  • 分享一个基于人脸识别的小区物业管理系统Spring Boot(源码、调试、LW、开题、PPT)
  • JS 中的深拷贝与浅拷贝
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • Angular4 模板式表单用法以及验证
  • centos安装java运行环境jdk+tomcat
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • ES6核心特性
  • GraphQL学习过程应该是这样的
  • HashMap剖析之内部结构
  • Javascript编码规范
  • Nodejs和JavaWeb协助开发
  • orm2 中文文档 3.1 模型属性
  • Sequelize 中文文档 v4 - Getting started - 入门
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • storm drpc实例
  • 初探 Vue 生命周期和钩子函数
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 官方解决所有 npm 全局安装权限问题
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 今年的LC3大会没了?
  • 漂亮刷新控件-iOS
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 前端_面试
  • 算法之不定期更新(一)(2018-04-12)
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 一个项目push到多个远程Git仓库
  • Hibernate主键生成策略及选择
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​Java并发新构件之Exchanger
  • #QT(串口助手-界面)
  • (¥1011)-(一千零一拾一元整)输出
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (第27天)Oracle 数据泵转换分区表
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (六)Flink 窗口计算
  • (强烈推荐)移动端音视频从零到上手(上)