Problem:
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.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Analysis:
This problem is interesting!!! It tests your coding skill and logic ability. Since h-index defines that at least h papers should exceed(include) h citation, you may wrongly think this is a simple count problem, why not use HashMap<citation, count>. However, even paper that have citation' larger than citation should be counted! What a pity, Right? Apparently the HashMap should not be used!!! Since there is good prperty : all papers have citation exceed certain index, could be counted for that index. Why not use sort??? Then, sorting the citation array in descending order, (i+1) is the total citations exceed citation[i]. Then I have following implementations:
Wrong solution 1:
public class Solution { public int hIndex(int[] citations) { if (citations == null) throw new IllegalArgumentException("The citaions' reference is null!"); Arrays.sort(citations, Collections.reverseOrder()); for (int i = 0; i < citations.length; i++) { if (i+1 >= citations[i]) return citations[i]; } return citations.length; } } Error: Line 5: error: no suitable method found for sort(int[],Comparator<Object>) Mistake 1: Arrays.sort(citations, Collections.reverseOrder()); Not work for primitive type, it only works for Integer, Double ....
Wrong solution 2:
Since we should give up the way of sorting citations in descending order, we should just use ascending order. For the citation in ascending order, citation[i]'s useful count is the number of papers after it (inclusive). for (int i = 0; i < citations.length; i++) { if (citations.length - i >= citations[i]) ... } public class Solution { public int hIndex(int[] citations) { if (citations == null) throw new IllegalArgumentException("The citaions' reference is null!"); Arrays.sort(citations); int max = -1; for (int i = 0; i < citations.length; i++) { if (citations.length - i >= citations[i]) max = Math.max(max, citations[i]); } return (max == -1 ? citations.length : max); } } Errors: Input: [4,4,0,0] Output: 0 Expected: 2 However, the above solution only consider the situation of "citations.length - i >= citations[i]" and no citation[i] is valid case (at the end). Even we may not be able to find citations[i] meet: if (citations.length - i >= citations[i]) max = Math.max(max, citations[i]); We still should have a valid h-index! Suppose we have no "citations.length - i >= citations[i]" case, it means citations.length - i < citations[i] since "citations[i]"" < "citations[citaions.length - i]"(thus all citations[i] account into citations[citaions.length - i]). Thus we must have (possible)hindex = citations.length - i.
Solution:
public class Solution { public int hIndex(int[] citations) { if (citations == null) throw new IllegalArgumentException("The citaions' reference is null!"); Arrays.sort(citations); int max = 0; for (int i = 0; i < citations.length; i++) { if (citations.length - i >= citations[i]) max = Math.max(max, citations[i]); else max = Math.max(max, citations.length - i); } return max; } }