package com.freetymekiyan.algorithms.level.medium; import org.junit.Assert; import org.junit.Test; /** * Follow up for H-Index: What if the citations array is sorted in ascending order? Could you optimize your algorithm? * <p> * Hint: * Expected runtime complexity is in O(log n) and the input is sorted. * <p> * Company Tags: Facebook * Tags: Binary Search * Similar Problems: (M) H-Index */ public class HIndex2 { /** * Binary Search. * Think about the definition of h index: h papers that have >= h citations. * If randomly pick an index in the citations array, mid. * The # of papers have >= h citations is: array length - mid. * If citations[mid] = length - mid, return mid. * If citations[mid] > length - mid, paper not enough, mid should be smaller. * If citations[mid] < length - mid, too many papers, mid should be larger. */ public int hIndex(int[] citations) { if (citations == null || citations.length == 0) { return 0; } int lo = 0; int hi = citations.length; int mid; while (lo < hi) { mid = lo + (hi - lo) / 2; if (citations[mid] >= citations.length - mid) { hi = mid; } else { lo = mid + 1; } } return citations.length - lo; // Cannot be citations[lo] since search might fail and lo can out of bounds. } @Test public void testExamples() { HIndex2 h2 = new HIndex2(); int ans; // [] -> 0 int[] citations1 = new int[0]; ans = h2.hIndex(citations1); Assert.assertEquals(0, ans); // [1] -> 1 int[] citations2 = new int[]{1}; ans = h2.hIndex(citations2); Assert.assertEquals(1, ans); // [1.2.3.4.5] -> 3 int[] citations3 = new int[]{1, 2, 3, 4, 5}; ans = h2.hIndex(citations3); Assert.assertEquals(3, ans); // [5,6,7,8,9] -> 5 int[] citations4 = new int[]{5, 6, 7, 8, 9}; ans = h2.hIndex(citations4); Assert.assertEquals(5, ans); } }