【Classic 150 刷题计划】 LeetCode 274. H 指数 | C++ 二分答案法 (单调性降维打击)

LeetCode 274. H 指数

📌 题目描述

题目级别:中等

给你一个整数数组 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 次,所以她的 h 指数是 3。

这道题除了常规的排序法以外,有一种极具"极客思维"的解法:二分答案。

为什么可以用二分?

因为 H 指数的成立条件具有绝对的单调性 。

假设我们在测试 H 指数是否能为 x:

  • 如果满足条件(有 ≥x\ge x≥x 篇文章引用数 ≥x\ge x≥x),说明答案至少 是 x,可能更大。
  • 如果不满足条件,说明答案必然小于 x。

算法流程:

  1. 观察题目给定的数据范围,引用次数 citations[i] <= 1000,且论文总数 N≤5000N \le 5000N≤5000。这意味着 H 指数最大不可能超过 1000。
  2. 我们定义搜索区间为 [0, 1000]。
  3. 每次取中间值 mid,遍历一次数组(check 函数),统计引用数 ≥mid\ge mid≥mid 的论文数量。
  4. 如果满足要求,则收缩左边界 l = mid;如果不满足,收缩右边界 r = mid - 1。
  5. 最终 l 停下的位置,就是能满足条件的最大 H 指数。

⚠️ 极客细节避坑:

当我们在二分查找中写下 l = mid 时,计算 mid 的公式必须是向上取整的 mid = (l + r + 1) / 2。如果不加 1,当 l 和 r 只差 1 时,mid 会向下取整等于 l,导致区间无法缩小,从而陷入死循环。


💻 C++ 代码实现 (原汁原味作者版)

cpp 复制代码
class Solution {
public:
    int hIndex(vector<int>& citations) {
        // 根据题目数据范围,H指数的最大值不可能超过 1000
        int l = 0, r = 1000;

        // 二分查找寻找最大的可行解
        while (l < r)
        {
            // 向上取整,配合 l = mid 避免死循环
            int mid = (l + r + 1) / 2;

            // 如果当前的 mid 满足 H 指数条件,说明答案在 [mid, r]
            if (check(citations, mid)) l = mid;
            // 否则说明 mid 太大了,答案在 [l, mid - 1]
            else r = mid - 1;
        }

        return l;
    }

    // 辅助函数:验证是否有至少 x 篇论文的引用量 >= x
    // 💡 工程小贴士:在实际工业代码中,这里建议修改为 const vector<int>& citations
    // 以避免每次调用 check 时产生高昂的数组拷贝开销
    bool check(vector<int> citations, int x)
    {
        int cnt = 0;
        for (int i = 0; i < citations.size(); i ++ )
        {
            if (citations[i] >= x) cnt ++ ;       
        }

        return cnt >= x;
    }
};
相关推荐
白杨尚青几秒前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
Jasmine_llq2 分钟前
《P17461 [GESP202609 八级] 生成树计数》
算法·栈·tarjan 算法·边双连通分量·深度优先搜索 dfs·tarjan 保存当前路径节点·模乘法
Jasmine_llq3 分钟前
《P17462 [GESP202609 八级] 末班车》
算法·dijkstra 算法·最大化版本,求最长可行值·建反向图(逆图 / 反转边)·多源 dijkstra 思想·对每个终点单独跑一遍djst·离线预处理 + 在线查询
the3clipse1 小时前
H.265熵编码核心:CABAC自适应二进制算术编码详解——如何将语法元素高效压缩为比特流
人工智能·算法·视频编码·h.265·hevc·cabac·cavlc
CQU_JIAKE1 小时前
10.4【A】
算法
Godspeed Zhao1 小时前
现代智能雷达技术19——算法(5)
算法
(Charon)1 小时前
【C++面试】RAII到底是什么:从资源管理理解C++对象生命周期
c++·算法·面试
无名猿1 小时前
成员初始化列表与初始化顺序陷阱:按声明顺序,不是书写顺序
c++·现代c++·语法基础
Omics Pro1 小时前
之江实验室NAR|虚拟细胞3阶段训练范式
数据库·人工智能·算法·机器学习·自然语言处理
Tisfy1 小时前
LeetCode 0678.有效的括号字符串:O(n)+O(1)一次遍历
算法·leetcode·字符串·题解·贪心·括号匹配