本文正在參加「Python主題月」,詳情查看 活動連接html
這是 LeetCode 上的 275. H 指數 II ,難度爲 中等。git
Tag : 「二分」github
給定一位研究者論文被引用次數的數組(被引用次數是非負整數),數組已經按照 升序排列 。編寫一個方法,計算出研究者的 h 指數。算法
h 指數的定義: 「h 表明「高引用次數」(high citations),一名科研人員的 h 指數是指他(她)的 (N 篇論文中)總共有 h 篇論文分別被引用了至少 h 次。(其他的 N - h 篇論文每篇被引用次數很少於 h 次。)"數組
示例:markdown
輸入: citations = [0,1,3,5,6]
輸出: 3
解釋: 給定數組表示研究者總共有 5 篇論文,每篇論文相應的被引用了 0, 1, 3, 5, 6 次。
因爲研究者有 3 篇論文每篇至少被引用了 3 次,其他兩篇論文每篇被引用很少於 3 次,因此她的 h 指數是 3。
複製代碼
說明:app
若是 h 有多有種可能的值 ,h 指數是其中最大的那個。less
進階:ide
本題與 274. H 指數 的主要不一樣有兩方面:函數
顯然,增長了數組有序特性,擴大了數據範圍。能夠猜到利用此特性,存在時間複雜度更低的算法實現。
check
)在 (題解) 274. H 指數 中,咱們使用了
的二分作法,算法的主要瓶頸在於
複雜度的 check
。
固然對於 的數據量,使用 複雜度沒有任何問題。
Java 代碼:
class Solution {
public int hIndex(int[] cs) {
int n = cs.length;
int l = 0, r = n;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(cs, mid)) l = mid;
else r = mid - 1;
}
return r;
}
boolean check(int[] cs, int mid) {
int ans = 0;
for (int i : cs) if (i >= mid) ans++;
return ans >= mid;
}
}
複製代碼
Python 3 代碼:
class Solution:
def hIndex(self, citations: List[int]) -> int:
def check(cs, mid):
return sum(i>=mid for i in cs) >= mid
n = len(citations)
l, r = 0, n
while l < r:
mid = l + r + 1 >> 1
if check(citations, mid):
l = mid
else:
r = mid - 1
return r
複製代碼
check
函數須要對數組進行線性遍歷,複雜度爲
。總體複雜度爲
在解法一中,顯然咱們沒有利用本題的「數組有序」的特性。
根據對 H 指數
定義,若是
升序,在最大的符合條件的分割點
的右邊(包含分割點),必然知足
,咱們應當對其進行計數,對於分割點的左邊,必然不知足
,無需進行計數。
所以,咱們能夠利用 分割點右邊書的個數與分割點 的大小關係進行二分 。
假設存在真實分割點下標
,其值大小爲
,分割點右邊的數值個數爲
,根據 H 指數
的定義,必然有
關係:
利用此「二段性」進行二分便可,二分出下標後,再計算出書的個數。
Java 代碼:
class Solution {
public int hIndex(int[] cs) {
int n = cs.length;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (cs[mid] >= n - mid) r = mid;
else l = mid + 1;
}
return cs[r] >= n - r ? n - r : 0;
}
}
複製代碼
Python 3 代碼:
class Solution:
def hIndex(self, citations: List[int]) -> int:
n = len(citations)
l, r = 0, n - 1
while l < r:
mid = l + r >> 1
if citations[mid] >= n - mid:
r = mid
else:
l = mid + 1
return n - r if citations[r] >= n - r else 0
複製代碼
題目 | 題解 | 難度 | 推薦指數 |
---|---|---|---|
4. 尋找兩個正序數組的中位數 | LeetCode 題解連接 | 困難 | 🤩🤩🤩🤩 |
29. 兩數相除 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
33. 搜索旋轉排序數組 | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩🤩 |
34. 在排序數組中查找元素的第一個和最後一個位置 | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩🤩 |
35. 搜索插入位置 | LeetCode 題解連接 | 簡單 | 🤩🤩🤩🤩🤩 |
74. 搜索二維矩陣 | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩 |
81. 搜索旋轉排序數組 II | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩 |
153. 尋找旋轉排序數組中的最小值 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
154. 尋找旋轉排序數組中的最小值 II | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
220. 存在重複元素 III | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
274. H 指數 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
278. 第一個錯誤的版本 | LeetCode 題解連接 | 簡單 | 🤩🤩🤩🤩 |
354. 俄羅斯套娃信封問題 | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
363. 矩形區域不超過 K 的最大數值和 | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
374. 猜數字大小 | LeetCode 題解連接 | 簡單 | 🤩🤩🤩 |
778. 水位上升的泳池中游泳 | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
852. 山脈數組的峯頂索引 | LeetCode 題解連接 | 簡單 | 🤩🤩🤩🤩🤩 |
981. 基於時間的鍵值存儲 | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩 |
1004. 最大連續1的個數 III | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
1011. 在 D 天內送達包裹的能力 | LeetCode 題解連接 | 中等 | 🤩🤩🤩🤩 |
1208. 儘量使字符串相等 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
1438. 絕對差不超過限制的最長連續子數組 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
1482. 製做 m 束花所需的最少天數 | LeetCode 題解連接 | 中等 | 🤩🤩🤩 |
1707. 與數組中元素的最大異或值 | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
1751. 最多能夠參加的會議數目 II | LeetCode 題解連接 | 困難 | 🤩🤩🤩 |
這是咱們「刷穿 LeetCode」系列文章的第 No.275
篇,系列開始於 2021/01/01,截止於起始日 LeetCode 上共有 1916 道題目,部分是有鎖題,咱們將先把全部不帶鎖的題目刷完。
在這個系列文章裏面,除了講解解題思路之外,還會盡量給出最爲簡潔的代碼。若是涉及通解還會相應的代碼模板。
爲了方便各位同窗可以電腦上進行調試和提交代碼,我創建了相關的倉庫:github.com/SharingSour… 。
在倉庫地址裏,你能夠看到系列文章的題解連接、系列文章的相應代碼、LeetCode 原題連接和其餘優選題解。