Skip to content

Commit 2596633

Browse files
committed
feat: add solutions to lc problem: No.0274
No.0274.H-Index
1 parent b3f15dc commit 2596633

File tree

7 files changed

+536
-169
lines changed

7 files changed

+536
-169
lines changed

solution/0200-0299/0274.H-Index/README.md

Lines changed: 242 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -43,114 +43,300 @@
4343

4444
<!-- 这里可写通用的实现逻辑 -->
4545

46-
最简单的解法就是排序之后再判断,但是因为 `H` 不可能大于论文的总数 `n`,所以可以用计数排序进行优化。
46+
**方法一:排序**
47+
48+
我们可以先对数组 `citations` 按照元素值从大到小进行排序。然后我们从大到小枚举 $h$ 值,如果某个 $h$ 值满足 $citations[h-1] \geq h$,则说明有至少 $h$ 篇论文分别被引用了至少 $h$ 次,直接返回 $h$ 即可。如果没有找到这样的 $h$ 值,说明所有的论文都没有被引用,返回 $0$。
49+
50+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 `citations` 的长度。
51+
52+
**方法二:计数 + 求和**
53+
54+
我们可以使用一个长度为 $n+1$ 的数组 $cnt$,其中 $cnt[i]$ 表示引用次数为 $i$ 的论文的篇数。我们遍历数组 `citations`,将引用次数大于 $n$ 的论文都当作引用次数为 $n$ 的论文,然后将每篇论文的引用次数作为下标,将 $cnt$ 中对应的元素值加 $1$。这样我们就统计出了每个引用次数对应的论文篇数。
55+
56+
接下来,我们从大到小枚举 $h$ 值,将 $cnt$ 中下标为 $h$ 的元素值加到变量 $s$ 中,其中 $s$ 表示引用次数大于等于 $h$ 的论文篇数。如果 $s \geq h$,说明至少有 $h$ 篇论文分别被引用了至少 $h$ 次,直接返回 $h$ 即可。
57+
58+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 `citations` 的长度。
59+
60+
**方法三:二分查找**
61+
62+
我们注意到,如果存在一个 $h$ 值满足至少有 $h$ 篇论文至少被引用 $h$ 次,那么对于任意一个 $h' \lt h$,都有至少 $h'$ 篇论文至少被引用 $h'$ 次。因此我们可以使用二分查找的方法,找到最大的 $h$ 值,使得至少有 $h$ 篇论文至少被引用 $h$ 次。
63+
64+
我们定义二分查找的左边界 $l=0$,右边界 $r=n$。每次我们取 $mid = \lfloor \frac{l + r + 1}{2} \rfloor$,其中 $\lfloor x \rfloor$ 表示对 $x$ 向下取整。然后我们统计数组 `citations` 中大于等于 $mid$ 的元素的个数,记为 $s$。如果 $s \geq mid$,说明至少有 $mid$ 篇论文至少被引用 $mid$ 次,此时我们将左边界 $l$ 变为 $mid$,否则我们将右边界 $r$ 变为 $mid-1$。当左边界 $l$ 等于右边界 $r$ 时,我们找到了最大的 $h$ 值,即为 $l$ 或 $r$。
65+
66+
时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 `citations` 的长度。空间复杂度 $O(1)$。
4767

4868
<!-- tabs:start -->
4969

5070
### **Python3**
5171

5272
<!-- 这里可写当前语言的特殊实现逻辑 -->
5373

74+
```python
75+
class Solution:
76+
def hIndex(self, citations: List[int]) -> int:
77+
citations.sort(reverse=True)
78+
for h in range(len(citations), 0, -1):
79+
if citations[h - 1] >= h:
80+
return h
81+
return 0
82+
```
83+
5484
```python
5585
class Solution:
5686
def hIndex(self, citations: List[int]) -> int:
5787
n = len(citations)
5888
cnt = [0] * (n + 1)
59-
for c in citations:
60-
if c <= n:
61-
cnt[c] += 1
89+
for x in citations:
90+
cnt[min(x, n)] += 1
91+
s = 0
92+
for h in range(n, -1, -1):
93+
s += cnt[h]
94+
if s >= h:
95+
return h
96+
```
97+
98+
```python
99+
class Solution:
100+
def hIndex(self, citations: List[int]) -> int:
101+
l, r = 0, len(citations)
102+
while l < r:
103+
mid = (l + r + 1) >> 1
104+
if sum(x >= mid for x in citations) >= mid:
105+
l = mid
62106
else:
63-
cnt[n] += 1
64-
sum = 0
65-
for i in range(n, -1, -1):
66-
sum += cnt[i]
67-
if sum >= i:
68-
return i
69-
return 0
107+
r = mid - 1
108+
return l
70109
```
71110

72111
### **Java**
73112

74113
<!-- 这里可写当前语言的特殊实现逻辑 -->
75114

115+
```java
116+
class Solution {
117+
public int hIndex(int[] citations) {
118+
Arrays.sort(citations);
119+
int n = citations.length;
120+
for (int h = n; h > 0; --h) {
121+
if (citations[n - h] >= h) {
122+
return h;
123+
}
124+
}
125+
return 0;
126+
}
127+
}
128+
```
129+
76130
```java
77131
class Solution {
78132
public int hIndex(int[] citations) {
79133
int n = citations.length;
80134
int[] cnt = new int[n + 1];
81-
for (int c : citations) {
82-
if (c <= n) {
83-
++cnt[c];
84-
} else {
85-
++cnt[n];
135+
for (int x : citations) {
136+
++cnt[Math.min(x, n)];
137+
}
138+
for (int h = n, s = 0; ; --h) {
139+
s += cnt[h];
140+
if (s >= h) {
141+
return h;
86142
}
87143
}
88-
int sum = 0;
89-
for (int i = n; i >= 0; --i) {
90-
sum += cnt[i];
91-
if (sum >= i) {
92-
return i;
144+
}
145+
}
146+
```
147+
148+
```java
149+
class Solution {
150+
public int hIndex(int[] citations) {
151+
int l = 0, r = citations.length;
152+
while (l < r) {
153+
int mid = (l + r + 1) >> 1;
154+
int s = 0;
155+
for (int x : citations) {
156+
if (x >= mid) {
157+
++s;
158+
}
159+
}
160+
if (s >= mid) {
161+
l = mid;
162+
} else {
163+
r = mid - 1;
93164
}
94165
}
95-
return 0;
166+
return l;
96167
}
97168
}
98169
```
99170

100-
### **TypeScript**
171+
### **C++**
101172

102-
```ts
103-
function hIndex(citations: number[]): number {
104-
let n = citations.length;
105-
let cnt = new Array(n + 1).fill(0);
106-
for (let c of citations) {
107-
if (c <= n) {
108-
++cnt[c];
109-
} else {
110-
++cnt[n];
173+
```cpp
174+
class Solution {
175+
public:
176+
int hIndex(vector<int>& citations) {
177+
sort(citations.rbegin(), citations.rend());
178+
for (int h = citations.size(); h; --h) {
179+
if (citations[h - 1] >= h) {
180+
return h;
181+
}
111182
}
183+
return 0;
112184
}
113-
let sum = 0;
114-
for (let i = n; i > -1; --i) {
115-
sum += cnt[i];
116-
if (sum >= i) {
117-
return i;
185+
};
186+
```
187+
188+
```cpp
189+
class Solution {
190+
public:
191+
int hIndex(vector<int>& citations) {
192+
int n = citations.size();
193+
int cnt[n + 1];
194+
memset(cnt, 0, sizeof(cnt));
195+
for (int x : citations) {
196+
++cnt[min(x, n)];
197+
}
198+
for (int h = n, s = 0;; --h) {
199+
s += cnt[h];
200+
if (s >= h) {
201+
return h;
202+
}
118203
}
119204
}
120-
return 0;
121-
}
205+
};
206+
```
207+
208+
```cpp
209+
class Solution {
210+
public:
211+
int hIndex(vector<int>& citations) {
212+
int l = 0, r = citations.size();
213+
while (l < r) {
214+
int mid = (l + r + 1) >> 1;
215+
int s = 0;
216+
for (int x : citations) {
217+
if (x >= mid) {
218+
++s;
219+
}
220+
}
221+
if (s >= mid) {
222+
l = mid;
223+
} else {
224+
r = mid - 1;
225+
}
226+
}
227+
return l;
228+
}
229+
};
122230
```
123231
124232
### **Go**
125233
126-
利用二分查找,定位符合条件的最大值
234+
```go
235+
func hIndex(citations []int) int {
236+
sort.Ints(citations)
237+
n := len(citations)
238+
for h := n; h > 0; h-- {
239+
if citations[n-h] >= h {
240+
return h
241+
}
242+
}
243+
return 0
244+
}
245+
```
127246

128247
```go
129248
func hIndex(citations []int) int {
130249
n := len(citations)
131-
left, right := 0, n
132-
for left+1 < right {
133-
mid := int(uint(left+right) >> 1)
134-
if check(citations, mid) {
135-
left = mid
136-
} else {
137-
right = mid
250+
cnt := make([]int, n+1)
251+
for _, x := range citations {
252+
cnt[min(x, n)]++
253+
}
254+
for h, s := n, 0; ; h-- {
255+
s += cnt[h]
256+
if s >= h {
257+
return h
138258
}
139259
}
140-
if check(citations, right) {
141-
return right
260+
}
261+
262+
func min(a, b int) int {
263+
if a < b {
264+
return a
142265
}
143-
return left
266+
return b
144267
}
268+
```
145269

146-
func check(citations []int, mid int) bool {
147-
cnt := 0
148-
for _, citation := range citations {
149-
if citation >= mid {
150-
cnt++
270+
```go
271+
func hIndex(citations []int) int {
272+
l, r := 0, len(citations)
273+
for l < r {
274+
mid := (l + r + 1) >> 1
275+
s := 0
276+
for _, x := range citations {
277+
if x >= mid {
278+
s++
279+
}
280+
}
281+
if s >= mid {
282+
l = mid
283+
} else {
284+
r = mid - 1
151285
}
152286
}
153-
return cnt >= mid
287+
return l
288+
}
289+
```
290+
291+
### **TypeScript**
292+
293+
```ts
294+
function hIndex(citations: number[]): number {
295+
citations.sort((a, b) => b - a);
296+
for (let h = citations.length; h; --h) {
297+
if (citations[h - 1] >= h) {
298+
return h;
299+
}
300+
}
301+
return 0;
302+
}
303+
```
304+
305+
```ts
306+
function hIndex(citations: number[]): number {
307+
const n: number = citations.length;
308+
const cnt: number[] = new Array(n + 1).fill(0);
309+
for (const x of citations) {
310+
++cnt[Math.min(x, n)];
311+
}
312+
for (let h = n, s = 0; ; --h) {
313+
s += cnt[h];
314+
if (s >= h) {
315+
return h;
316+
}
317+
}
318+
}
319+
```
320+
321+
```ts
322+
function hIndex(citations: number[]): number {
323+
let l = 0;
324+
let r = citations.length;
325+
while (l < r) {
326+
const mid = (l + r + 1) >> 1;
327+
let s = 0;
328+
for (const x of citations) {
329+
if (x >= mid) {
330+
++s;
331+
}
332+
}
333+
if (s >= mid) {
334+
l = mid;
335+
} else {
336+
r = mid - 1;
337+
}
338+
}
339+
return l;
154340
}
155341
```
156342

0 commit comments

Comments
 (0)