[M二分] lc275. H 指数 II(二分答案+二分下标+二分坑点)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M二分] lc275. H 指数 II(二分答案+二分下标+二分坑点)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:275. H 指数 II

相关:[M排序] lc274. H 指数(排序+模拟)

2. 题目解析

二分,有坑点。

两种思路,二分答案 h,或者二分下标。但是二分下标有点小坑…

二分下标:

  • 下标范围 0~n-1,很自然,l=0, r=n-1,但是当 n=1 时,就根本进不去 while 循环…被坑,提交后 WA1
  • citations[mid] >= n - mid 时,显然就是 r=mid,因为要找最大的 h,相当于尽量往小下标找。
  • 由于是二分下标,一定会停到下标的位置上 l=r 是最终停下位置,那么 n-l 就是 h 的数量。
  • 但是,当输入是 [0],或者 [0, 0, 0] 这样全 0 数组时,即触发无解情况时,会停到 l=r=n-1 的位置,那么最终答案返回 n-l=1 就是错误的,应当返回 0。
  • 所以使用下标进行二分,最终需要判断答案正确性。 被坑两次,做出总结。

二分答案:

  • 也可以直接针对 h 进行二分,进行坐标变换即可。
  • l=0, r=n,当 citations[n - mid] >= mid 时, l = mid 尽量往左找。
  • 这样就少了很多边界情况,方便判断了。

时间复杂度: O ( l o g n ) O(logn) O(logn)
空间复杂度: O ( 1 ) O(1) O(1)


class Solution {
public:
    int hIndex(vector<int>& citations) {
        int n = citations.size();
        int l = 0, r = n - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (citations[mid] >= n - mid) r = mid;
            else l = mid + 1;
        }
        if (citations[l] < n - l) return 0;           // 二分下标,这步判断很重要
        return n - l;
    }
};

二分答案,没有边界情况,很舒服!

class Solution {
public:
    int hIndex(vector<int>& citations) {
        int n = citations.size();
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (citations[n - mid] >= mid) l = mid;
            else r = mid - 1;
        }
        return l;
    }
};

以上是关于[M二分] lc275. H 指数 II(二分答案+二分下标+二分坑点)的主要内容,如果未能解决你的问题,请参考以下文章

二分查找算法复习

LeetCode 275. H 指数 II

275 H-Index II H指数 II

275. H 指数 II

275. H 指数 II--Leetcode_暴力

[LeetCode] 275. H-Index II H指数 II