LeetCode题练习与总结:H 指数 Ⅱ--275
一、题目描述
给你一个整数数组 citations
,其中 citations[i]
表示研究者的第 i
篇论文被引用的次数,citations
已经按照 升序排列 。计算并返回该研究者的 h 指数。
h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h
指数是指他(她)的 (n
篇论文中)至少 有 h
篇论文分别被引用了至少 h
次。
请你设计并实现对数时间复杂度的算法解决此问题。
示例 1:
输入:citations = [0,1,3,5,6]
输出:3
解释:给定数组表示研究者总共有5
篇论文,每篇论文相应的被引用了0, 1, 3, 5, 6
次。由于研究者有3
篇论文每篇 至少 被引用了3
次,其余两篇论文每篇被引用 不多于3
次,所以她的 h 指数是3
。
示例 2:
输入:citations = [1,2,100]
输出:2
提示:
n == citations.length
1 <= n <= 10^5
0 <= citations[i] <= 1000
citations
按 升序排列
二、解题思路
- 首先,根据题目要求,我们需要找到最大的 h 值,使得至少有 h 篇论文的引用次数大于或等于 h。
- 因为数组已经按照升序排列,我们可以使用二分查找的方法来寻找这个 h 值。
- 在二分查找的过程中,我们需要检查 mid 位置的引用次数是否满足条件,即
citations[mid] >= n - mid
,其中 n 是数组的长度。 - 如果满足条件,说明可能存在更大的 h 值,因此我们将 left 移动到 mid + 1 的位置继续查找。
- 如果不满足条件,说明 h 值应该小于 mid,因此我们将 right 移动到 mid - 1 的位置继续查找。
- 当 left 超过 right 时,停止查找,此时 right 就是我们要找的 h 值。
三、具体代码
class Solution {public int hIndex(int[] citations) {int n = citations.length;int left = 0, right = n - 1;while (left <= right) {int mid = left + (right - left) / 2;if (citations[mid] >= n - mid) {// 满足条件,可能存在更大的 h 值right = mid - 1;} else {// 不满足条件,h 值应该小于 midleft = mid + 1;}}// 当循环结束时,right + 1 就是 h 指数return n - left;}
}
这段代码中,left
最终会停在第一个不满足 citations[mid] >= n - mid
的位置,而 n - left
就是我们要求的 h 指数。因为 left
指向的是第一个引用次数小于论文数量的索引,所以 n - left
就是从该索引到数组末尾的论文数量,即至少有 n - left
篇论文的引用次数大于或等于 n - left
。
四、时间复杂度和空间复杂度
1. 时间复杂度
- 代码中使用了二分查找算法,其核心是一个 while 循环,该循环会在每次迭代中将搜索范围减半。
- 在最坏的情况下,循环会执行直到
left
超过right
,即当搜索范围缩小到无法再进行分割时。 - 在每次迭代中,搜索范围都会从
[left, right]
变为[left, mid - 1]
或[mid + 1, right]
,其中mid
是当前搜索范围的中间值。 - 因此,循环的次数大约是
log(n)
,其中n
是数组citations
的长度。
综上所述,该算法的时间复杂度是 O(log n),即对数时间复杂度。
2. 空间复杂度
- 空间复杂度主要考虑算法执行过程中所使用的额外空间。
- 在这段代码中,我们使用了常数个额外空间,即
left
、right
和mid
这三个整型变量。 - 这些变量占用的空间不会随着输入数组
citations
的大小而改变。
因此,该算法的空间复杂度是 O(1),即常数空间复杂度。
五、总结知识点
-
类定义:
class Solution
定义了一个名为Solution
的类。
-
方法定义:
public int hIndex(int[] citations)
定义了一个公共方法hIndex
,它接受一个整数数组citations
作为参数,并返回一个整数。
-
变量声明和初始化:
int n = citations.length;
声明并初始化了一个整数变量n
,用于存储数组citations
的长度。int left = 0, right = n - 1;
同时声明并初始化了两个整数变量left
和right
,分别用于二分查找的左右边界。
-
循环结构:
while (left <= right)
使用了一个while
循环来执行二分查找,直到left
大于right
。
-
二分查找算法:
int mid = left + (right - left) / 2;
计算中间位置mid
,防止left
和right
相加时可能发生的整数溢出。- 根据中间位置的值与
n - mid
的比较结果来调整搜索范围。
-
条件判断:
if (citations[mid] >= n - mid)
检查中间位置的论文引用次数是否满足 h 指数的条件。else
分支处理不满足条件的情况。
-
数组访问:
citations[mid]
访问数组citations
中索引为mid
的元素。
-
整数运算:
- 使用基本的整数加减和比较运算来调整
left
和right
的值。
- 使用基本的整数加减和比较运算来调整
-
算法逻辑:
- 代码的逻辑基于二分查找算法,用于在有序数组中找到满足特定条件的最大值。
-
边界条件处理:
- 在二分查找的过程中,通过调整
left
和right
的值来缩小搜索范围,直到找到正确的 h 指数。
- 在二分查找的过程中,通过调整
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。