H-Index [LeetCode] | Training dragons the hard way - Programming Every Day!


H-Index [LeetCode] | Training dragons the hard way - Programming Every Day!
Given an array of citations (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index.
According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each."
For example, given citations = [3, 0, 6, 1, 5], which means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively. Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, his h-index is 3.
Note: If there are several possible values for h, the maximum one is taken as the h-index.
As we know, H-Index is a measure of productivity and citation impact of a researcher. It is also called Hirsch index or Hirsch number after the name of the physicist Jorge Hirsch.
Picture 1: H-Index for decreasing citations array (Credit: Wiki)

Supposed that citations is an array of numbers of citations of a researcher. We can easily see that the following formula holds if citations is sorted in decreasing order:

h-index of citations = max (min (citations[i], i) for all i from 1 to number of papers)
X. O(N)
We have some simple observation here, but it really helps to improve the performance. For each number h from 0 to where is the number of papers, we need to find out how many citations of a paper equal called equal_h. Based on this, we can find the number of citations values that is at least h, and no more than h. To find the number of citations value that is at least h, we take sum of equal_h[i] for i from h to n!!! And similarly, to find the number of citations values that is no more than citations each, we can sum up equal_h[i] for ifrom 0 to i. And we can find the h-index by simple running from the back of the array equal_h.
So if running from the back of the array equal_h , and h is the first index that satisfies the following conditions:
equal_h[h] + equal_h[h+1] + ... + equal_h[n] >= h (*) 
equal_h[0] + equal_h[1] + ... + equal_h[h] >= N-h (**) 
Then is what we are looking for. 
However, we have: 
equal_h[0] + equal_h[1] + ... + equal_h[n] = n 
Therefore: 
equal_h[0] + equal_h[1] + ... + equal_h[h] = n- (equal_h[h+1] + ... + equal_h[n]) 
Another note is that since h is the first element satisfies the 2 above conditions, then h+1 does not satisfies one of them, meaning that either
(1): { equal_h[h+1] + equal_h[h+2] + ... + equal_h[n] <= h 
or (2): { equal_h[h+1] + equal_h[h+2] + ... + equal_h[n] >= h+1 
and equal_h[0] + equal_h[1] + ... + equal_h[h+1] < N-(h+1) } 
(1) suggests that: 
equal_h[0] + equal_h[1] + ... + equal_h[h] >=N-h which is (**)
(2) suggests that: 
equal_h[h+2] + equal_h[h+3] + ... + equal_h[n] >= h+2 
This inequality will be repeated until equal_h[n] >= n , which is wrong.

So all we need is to find the first satisfies the condition (*), and we do not need to check the condition (**).

  1.     public int hIndex(int[] citations) {  
  2.         int n = citations.length;  
  3.         int [] equal_h = new int[n+1];  
  4.         for (int h = 0; h<n; h++){  
  5.             if(citations[h] >= n) equal_h[n] += 1;  
  6.             else equal_h[citations[h]] += 1;  
  7.         }  
  8.         int s = 0//we don't need check overflow here coz sum always <= n  
  9.         for (int h = n; h>0; h--){  
  10.             s += equal_h[h];  
  11.             if (s >= h) return h;  
  12.               
  13.         }  
  14.         return 0;  
  15.     } 
http://segmentfault.com/a/1190000003794831
时间 O(NlogN) 空间 O(1)
先将数组排序,我们就可以知道对于某个引用数,有多少文献的引用数大于这个数。对于引用数citations[i],大于该引用数文献的数量是citations.length - i,而当前的H-Index则是Math.min(citations[i], citations.length - i),我们将这个当前的H指数和全局最大的H指数来比较,得到最大H指数。
    public int hIndex(int[] citations) {
        // 排序
        Arrays.sort(citations);
        int h = 0;
        for(int i = 0; i < citations.length; i++){
            // 得到当前的H指数
            int currH = Math.min(citations[i], citations.length - i);
            if(currH > h){
                h = currH;
            }
        }
        return h;
    }
http://www.neozone.me/leetcode274.html
时间 O(N) 空间 O(N)
也可以不对数组排序,我们额外使用一个大小为N+1的数组stats。stats[i]表示有多少文章被引用了i次,这里如果一篇文章引用大于N次,我们就将其当为N次,因为H指数不会超过文章的总数。为了构建这个数组,我们需要先将整个文献引用数组遍历一遍,对相应的格子加一。统计完后,我们从N向1开始遍历这个统计数组。如果遍历到某一个引用次数时,大于或等于该引用次数的文章数量,大于引用次数本身时,我们可以认为这是H指数。之所以不用再向下找,因为我们要取最大的H指数。那如何求大于或等于某个引用次数的文章数量呢?我们可以用一个变量,从高引用次的文章数累加下来。因为我们知道,如果有x篇文章的引用大于等于3次,那引用大于等于2次的文章数量一定是x加上引用次数等于2次的文章数量。
    public int hIndex(int[] citations) {
        int[] stats = new int[citations.length + 1];
        int n = citations.length;
        // 统计各个引用次数对应多少篇文章
        for(int i = 0; i < n; i++){
            stats[citations[i] <= n ? citations[i] : n] += 1;
        }
        int sum = 0;
        // 找出最大的H指数
        for(int i = n; i > 0; i--){
            // 引用大于等于i次的文章数量,等于引用大于等于i+1次的文章数量,加上引用等于i次的文章数量 
            sum += stats[i];
            // 如果引用大于等于i次的文章数量,大于引用次数i,说明是H指数
            if(sum >= i){
                return i;
            }
        }
        return 0;
    }
http://blog.welkinlan.com/2015/11/05/h-index-i-ii-leetcode-java/
    public int hIndex(int[] citations) {
        int n = citations.length;
        int[] count = new int[n + 1];
        for (int i = 0; i < n; i++) {
            if (citations[i] > n) count[n]++;
            else count[citations[i]]++;
        }
        for (int i = n; i > 0; i--) {
            if (count[i] >= i) return i;
            count[i-1] += count[i];
        }
        return 0;
    }
https://github.com/kamyu104/LeetCode/blob/master/C++/h-index.cpp
int hIndex(vector<int>& citations) {
const auto n = citations.size();
vector<int> count(n + 1, 0);
for (const auto& x : citations) {
// Put all x >= n in the same bucket.
if (x >= n) {
++count[n];
} else {
++count[x];
}
}
int h = 0;
for (int i = n; i >= 0; --i) {
h += count[i];
if (h >= i) {
return i;
}
}
return h;
}
http://bookshadow.com/weblog/2015/09/03/leetcode-h-index/
使用长度为N + 1的数组cnts记录引用次数在0 ~ N(N篇以上的记为N)的文章个数
然后遍历cnts数组,计算h值的最大值
def hIndex(self, citations): N = len(citations) cnts = [0] * (N + 1) for c in citations: cnts[[c, N][c > N]] += 1 sums = 0 for h in range(N, 0, -1): if sums + cnts[h] >= h: return h sums += cnts[h] return 0
X. O(NlogN)
http://segmentfault.com/a/1190000003794831
先将数组排序,我们就可以知道对于某个引用数,有多少文献的引用数大于这个数。对于引用数citations[i],大于该引用数文献的数量是citations.length - i,而当前的H-Index则是Math.min(citations[i], citations.length - i),我们将这个当前的H指数和全局最大的H指数来比较,得到最大H指数。
    public int hIndex(int[] citations) {
        // 排序
        Arrays.sort(citations);
        int h = 0;
        for(int i = 0; i < citations.length; i++){
            // 得到当前的H指数
            int currH = Math.min(citations[i], citations.length - i);
            if(currH > h){
                h = currH;
            }
        }
        return h;
    }
http://www.neozone.me/leetcode274.html
现将数组排序。然后从大到小遍历,一边计数一边比较计数与当前的引用数,直到计数大于引用数。
    public int hIndex(int[] citations) {
        if(citations == null || citations.length == 0) return 0;
        Arrays.sort(citations);
        int count = 0;
        for(int i = citations.length - 1; i >= 0; i--){
            if(++count > citations[i]) {
                count--;
                break;
            }
        }
        return count;
    }
http://www.cnblogs.com/grandyang/p/4781203.html
Therefore, we can easily implement the calculation of h-index by sorting the array in decreasing order then applying the above formula.
  1.     def hIndex(self, citations):  
  2.         """ 
  3.         :type citations: List[int] 
  4.         :rtype: int 
  5.         """  
  6.         citations.sort(reverse=True)  
  7.         return max([min(k+1, v) for k,v in enumerate(citations)]) if citations else 0 
https://leetcode.com/discuss/55924/o-nlogn-12ms-solution
int hIndex(vector<int>& citations) { if(citations.empty()) return 0; sort(citations.begin(), citations.end()); int n=citations.size(); int i=0; while(i<n && citations[i]<(n-i)) i++; return n-i; }

这道题让我们求H指数,这个质数是用来衡量研究人员的学术水平的质数,定义为一个人的学术文章有n篇分别被引用了n次,那么H指数就是n。而且wiki上直接给出了算法,可以按照如下方法确定某人的H指数:1、将其发表的所有SCI论文按被引次数从高到低排序;2、从前往后查找排序后的列表,直到某篇论文的序号大于该论文被引次数。所得序号减一即为H指数。
    int hIndex(vector<int>& citations) {
        sort(citations.begin(), citations.end(), greater<int>());
        for (int i = 0; i < citations.size(); ++i) {
            if (i >= citations[i]) return i;
        }
        return citations.size();
    }
https://github.com/kamyu104/LeetCode/blob/master/C++/h-index.cpp
Not good idea to use iterator or for loop here, as we need use the index.
int hIndex(vector<int>& citations) { sort(citations.begin(), citations.end(), greater<int>());
int h = 0;
for (const auto& x : citations) {
if (x >= h + 1) {
++h;
} else {
break;
}
}
return h;
}

(2):按照文章引用次数正序排列,循环遍历数组,统计min(引用次数c, 剩余文章篇数N-i)的最大值
def hIndex(self, citations): N = len(citations) for i, c in enumerate(sorted(citations)): if N - i <= c: return N - i return 0
Techinpad: [LeetCode] H-Index
public int hIndex(int[] c) { if (c == null) { return 0; } List<Integer> rsorted = Arrays.stream(c).mapToObj(i->Integer.valueOf(i)).
sorted(Collections.reverseOrder()).collect(Collectors.toList()); return IntStream.range(0,rsorted.size()).
reduce(0,(hindex,curindex)->Math.max(hindex,Math.min(curindex+1,rsorted.get(curindex)))); }
http://www.fgdsb.com/2015/01/07/find-h/
一个array里面找最大的这样的h: 至少有h个数大于等于h。
比如{2,3,5}答案是2,{5,6,7,8}答案是4。
可以用quick select的思路来做,平均时间复杂度O(n),空间O(1)
可以用quick select的思路来做,平均时间复杂度O(n),空间O(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int find_h_s( std::vector<int> arr ){
int ret = 0;
for(int low = 0, high = (int)arr.size(); low < high;){
int n = low + (high - low) / 2;
nth_element(arr.begin()+low, arr.begin()+n, arr.begin()+high, greater<int>());
if(arr[n] >= n+1){
ret = max(ret, n+1);
low = n+1;
} else {
high = n;
}
}
return ret;
}
如果允许extra memory的话可以用counting的思路做,更简单,时间和空间都是O(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
int find_h_c(vector<int> a) {
int n = (int)a.size();
vector<int> m(n+1, 0);
for(auto num : a) {
if(num >= n) ++m[n];
else ++m[num];
}
for(int i = n, sum = 0; i > 0; --i) {
sum += m[i];
if(sum >= i) return i;
}
return 0;
}
还可以先排序,然后直接扫一遍,时间复杂度就是排序的复杂度。
1
2
3
4
5
6
7
8
int find_h_sort(vector<int> a) {
sort(a.begin(), a.end(), greater<int>());
for(int i = (int)a.size(); i > 0; --i) {
if(a[i-1] >= i) return i;
}
return 0;
}

Read full article from H-Index [LeetCode] | Training dragons the hard way - Programming Every Day!

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts