【刷题笔记】H指数||数组||二分查找的变体

H指数

最新编辑于2023.11.29
之前的代码写得有点抽象,实在抱歉,好像我自己都不理解当时自己怎么写的,现在重新更新了代码,保证好理解。

1 题目描述

https://leetcode.cn/problems/h-index/

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

示例 2:

输入:citations = [1,3,1]
输出:1


2 思路

反正不是我想出来的,随便写写

解题方法来源

这道题也是一道“翻译不当人”的典范,我们可以将这句话重新翻译一下

找到一个阈值h,数组中大于等于h的元素数量也大于等于h。同时保证阈值为h+1的时候,找不到足够数量的元素个数。

然后我们更加格式化地理解一下上面这句话:假设有一个统计函数counter(c)来统计数组中大于等于c的元素个数,counter(h) >= h, counter(h+1) < h+1

比如我们设citations=[13, 7, 6, 18, 12, 20, 20, 3, 0, 7],我们用gif的形式来表现当c=1、2、3...10的时候,数组中满足条件的元素个数。

在这里插入图片描述

counter(1) = 9 >= 1
counter(2) = 9 >= 2
counter(3) = 9 >= 3
counter(4) = 8 >= 4
counter(5) = 8 >= 5
counter(6) = 8 >= 6
counter(7) = 7 >= 7
-------------------
counter(8) = 5 < 8
counter(9) = 5 < 9
counter(10) = 5 < 10

我们用下图表示:

在这里插入图片描述

假设我们有一个数组[1, 2, ... , len(citiations)](设为nums),其中一定有一个分界线h,左和右分别表示满足或者不满足条件。

而当我们将上述数组替换成counter(c),即counters

在这里插入图片描述

很明显,counters数组是一个有序的、递减的数组。

在这里插入图片描述

好像事情朝着有趣的方向发展了,我们有一个有序数组counters,我们有一个判定条件counters[i] >= i+1(i在这里是下标),我们需要从有序数组中找到最后一个符合条件的元素

But, 如果我们对[1, 2, ... , len(citiations)](设为nums)数组进行遍历,对每个元素都施加counter函数来获得最终的counters数组,太耗时了。我们看看,能不能对上面的表述进行一些改造,毕竟nums和counters是一一对应的,我们可以在遍历到nums对应的元素时,再计算对应的counter:

我们有一个有序数组[1, 2, … , len(citiations)](表示为nums),我们有一个判定条件counter(nums[i]) >= i+1(i在这里是下标),我们需要从有序数组中找到最后一个符合条件的元素

在二分法中,我比较喜欢直接使用第1个元素、第2个元素、……、第n个元素这样的方式来指示元素的位置。

二分法中具有两个关键问题:

  • mid元素的下标计算
  • left指针和right指针的跳转方式

mid的计算,其实和left以及right指针的跳转方式相关。比如我们这个题目中,需要找到最后一个符合条件的元素。

也就是说,假设counter(nums[mid]) >= nums[mid],我们知道nums[mid]满足条件,但是nums[mid+1]还满足吗?不一定!所以left就 不能 直接跳转到mid的右边,而是 只能 直接跳转到mid上。

 if (counter(cs, nums[mid_index]) >= nums[mid_index]) {l = real_mid;} else {r = real_mid - 1;}

在这里插入图片描述

那么我们如何计算mid呢?这就需要我们考虑当只剩下两个元素的时候,mid到底是在left上还是在right上。如果让mid=left,下一步如果left需要跳转,left=mid,然后mid=left。。。。。。无限循环。

所以我们先看怎么跳转,再回过头想怎么计算mid。

也就是说,如果当前的[left~right]之间的元素个数为偶数,我们需要让mid指针指向中间两个元素的后一个元素。

class Solution {public int hIndex(int[] cs) {int[] nums = new int[cs.length];for (int i = 0; i < cs.length; i++) {nums[i] = i + 1;}int l = 1;int r = cs.length;while (l < r) {int real_mid = (l + r) / 2 + ((l - r + 1) % 2 == 0 ? 1 : 0); // 如果l~r的元素个数为奇数个,(l+r) / 2 就是中间元素的真实位置// 如果l-r的元素个数为偶数个,(l+r) / 2 就是中间两个的元素的靠左的元素,所以要+1// 变成中间两个元素靠右的位置。int mid_index = real_mid - 1;if (counter(cs, nums[mid_index]) >= nums[mid_index]) {l = real_mid; // left转移到mid} else {r = real_mid - 1; // right转移到mid - 1}}return counter(cs, l) >= l ? l : 0; // 有两种情况,一个是cs中只有一个元素,另一种情况是所有元素都为0}int counter(int[] cs, int mid) {int ans = 0;for (int i : cs) if (i >= mid) ans++; // 计算citiations中大于等于mid的元素数量。return ans;}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/206611.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python基础学习之包与模块详解

文章目录 前言什么是 Python 的包与模块包的身份证如何创建包创建包的小练习 包的导入 - import模块的导入 - from…import导入子包及子包函数的调用导入主包及主包的函数调用导入的包与子包模块之间过长如何优化 强大的第三方包什么是第三方包如何安装第三方包 总结关于Python…

【人工智能Ⅰ】实验3:蚁群算法

实验3 蚁群算法的应用 一、实验内容 TSP 问题的蚁群算法实现。 二、实验目的 1. 熟悉和掌握蚁群算法的基本概念和思想&#xff1b; 2. 理解和掌握蚁群算法的参数选取&#xff0c;解决实际应用问题。 三、实验原理 1&#xff0e;算法来源 蚁群算法的基本原理来源于自然界…

网络基础_1

目录 网络基础 协议 协议分层 OSI七层模型 网络传输的基本流程 数据包的封装和分用 IP地址和MAC地址 网络基础 网络就是不同的计算机之间可以进行通信&#xff0c;前面我们学了同一台计算机之间通信&#xff0c;其中有进程间通信&#xff0c;前面学过的有管道&#xff…

在Linux上安装KVM虚拟机

一、搭建KVM环境 KVM&#xff08;Kernel-based Virtual Machine&#xff09;是一个基于内核的系统虚拟化模块&#xff0c;从Linux内核版本2.6.20开始&#xff0c;各大Linux发行版就已经将其集成于发行版中。KVM与Xen等虚拟化相比&#xff0c;需要硬件支持的完全虚拟化。KVM由内…

百度人工智能培训第二天笔记

参加了百度人工智能初步培训&#xff0c;主要是了解一下现在人工智能的基本情况&#xff0c;以便后续看可以参与一些啥&#xff1f; 下面就继续前一天的内容记录。 一、先做电动自行车的电梯里检测 先进行图片资料的上传与标注&#xff0c;这个昨天的最好也说了一下。 训练完后…

手摸手Element-ui组件化开发

前端环境准备 编码工具: VSCode 依赖管理:NPM 项目构建: Vuecli NPM的全称是Node Package Manager&#xff0c;是一个NodeJS包管理和分发工具&#xff0c;已经成为了非官方的发布Node模块&#xff08;包&#xff09;的标准。2020年3月17日&#xff0c;Github宣布收购npm&am…

WebGL/threeJS面试题扫描与总结

什么是 WebGL&#xff1f;什么是 Three.js&#xff1f;请解释three.js中的WebGL和Canvas的区别&#xff1f; WebGL(全写Web Graphics Library)是一种3D绘图协议&#xff0c;这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起&#xff0c;通过增加OpenGL ES 2.0的一个…

龙芯loongarch64服务器编译安装pyarrow

1、简介 pyarrow是一个高效的Python库,用于在Python应用程序和Apache Arrow之间进行交互。Arrow是一种跨语言的内存格式,可以快速高效地转移大型数据集合。它提供了一种通用的数据格式,将数据在内存中表示为表格,并支持诸如序列化和分布式读取等功能。 龙芯的Python仓库安…

【教程】 一文部署配置并入门 Redis

综述 什么是Redis Redis官网——Redis.io Redis, 作为一个高性能的键值对数据库&#xff0c;主要应用于以下场景&#xff1a; 缓存系统&#xff1a;由于其高速读写能力&#xff0c;Redis 非常适合用作缓存系统&#xff0c;减少数据库负载。 会话存储&#xff08;Session St…

构建未来:云计算 生成式 AI 诞生科技新局面

目录 引言生成式 AI&#xff1a;开发者新伙伴云计算与生成式 AI 的无缝融合亚马逊云与生成式 AI 结合的展望/总结我用亚马逊云科技生成式 AI 产品打造了什么&#xff0c;解决了什么问题未来科技发展趋势&#xff1a;开发者的机遇与挑战结合实践看未来结语开源项目 引言 2023年…

基于SpringBoot母婴商城

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本母婴商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

04.里氏替换原则(Liskov Substitution Principle)

暴论&#xff1a;一般的&#xff0c;如果一个富二代不想着证明自己&#xff0c;那么他一辈子都会衣食无忧。 一言 里氏替换原则想告诉我们在继承过程中会遇到什么问题&#xff0c;以及继承有哪些注意事项。 概述 这是流传较广的一个段子&#xff1a; “一个坐拥万贯家财的富二…

DBS note6:Hashing(哈希存储)

目录 一、一般策略 二、算法简述 三、哈希缺点&#xff08;Drawbacks of Hashing&#xff09; 四、举例 五、外部哈希的分析 一、一般策略 由于我们无法一次性将所有数据放入内存中&#xff0c;我们需要构建多个不同的哈希表并将它们连接在一起。然而&#xff0c;这个想法…

第20 章 多线程

20.1线程简介. 20.2创建线程 2.1继承Thread类 Thread 类是java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立Thread 实例。Thread类中常用的两个构造方法如下: public Thread():创建一个新的线程对象。 public Threa…

如何提高3D建模技能?

无论是制作影视动画还是视频游戏&#xff0c;提高3D建模技能对于你的工作都至关重要的。那么如何能创建出精美的3D模型呢&#xff1f;本文给大家一些3D建模技能方面的建议。 3D建模通过专门的软件完成&#xff0c;涉及制作三维对象。这项技能在视频游戏开发、建筑、动画和产品…

18、串口通信

串口介绍 串口是一种应用十分广泛的通讯接口&#xff0c;串口成本低、容易使用、通信线路简单&#xff0c;可实现两个设备的互相通信。 单片机的串口可以使单片机与单片机&#xff0c;单片机与电脑、单片机与各式各样的模块互相通信&#xff0c;极大的扩展了单片机的应用范围&…

大模型能否生成搜索引擎的未来?

文&#xff5c;郝 鑫 编&#xff5c;刘雨琦 ChatGPT火爆之前&#xff0c;水面下&#xff0c;也有中国公司也在朝着智能助手的方向努力。夸克便是其中之一。在GPT风靡科技圈后&#xff0c;国内就开始陆续冒出一些大模型厂商。对当时夸克而言&#xff0c;做大模型毋庸置疑&am…

Python list列表添加元素的3种方法及删除元素的3种方法

Python list列表添加元素的3种方法 Python list 列表增加元素可调用列表的 append() 方法&#xff0c;该方法会把传入的参数追加到列表的最后面。 append() 方法既可接收单个值&#xff0c;也可接收元组、列表等&#xff0c;但该方法只是把元组、列表当成单个元素&#xff0c;这…

“逆风飞翔·事实孤儿同行计划”成长陪伴主题区域陪伴培训会

为推进各机构更好地开展事实孤儿成长陪伴工作&#xff0c;促进事实孤儿成长陪伴实施成效&#xff0c;搭建各机构间事实孤儿成长陪伴方式方法交流平台。11月26日&#xff0c;在中国乡村发展基金会、中国民生银行的支持下&#xff0c;由湖南省大爱无疆青少年公益发展中心主办&…

ZZULIOJ 2466: 楼上瞎说,楼下才是,Java

2466: 楼上瞎说&#xff0c;楼下才是 题目描述 《九章算术》的内容十分丰富&#xff0c;全书采用问题集的形式&#xff0c;收有246个与生产、生活实践有联系的应用问题&#xff0c;其中每道题有问&#xff08;题目&#xff09;、答&#xff08;答案&#xff09;、术&#xff…