Mathwizurd.com is created by David Witten, a mathematics and computer science student at Vanderbilt University. For more information, see the "About" page.

Problem

You’re given an array [1,3,5,0,6,5,7] of non-negative integers. Return the h-index of this array, which is the largest number with at least that many elements. In this case, there are 3 elements >= 3 and 2 elements >= 4, so the H-index is 3.

Thought Process

First, let’s think. What’s the largest possible h-index? 5, because there are 5 elements in the list. What’s the lowest possible h-index? 0, because all elements are non-negative.

What if we sorted the array?

If the array is sorted, it’s easy to see how many elements are greater than or equal to it.

Let’s go through the array now.

[0, 1, 3, 5, 6, 6, 7]

There are 7 elements greater than or equal to 0.

There are 6 elements greater than or equal to 1.

There are 5 elements greater than or equal to 3.

There are 4 elements greater than or equal to 5.

XXXXXXXXXXX

We terminate our algorithm. We have 4 elements greater than or equal to 5. The last number that worked was 3, but we have a little bit more information. If we know 4 elements are >= 5, then 4 elements are also >= 4, so we have our answer. 4

Code

def determine(array):
array = sorted(array)# sort the array
if array == []: #Edge case
return 0
length = len(array)
for index,element in enumerate(array):
if element >= length - index:
return length - index
return 0

Can we do better?

This runs in O(n log n) time because we have to sort the array. For an unsorted array, we must use all n data points in the array, so there’s no way we can do it in less than O(n) time.

Therefore, let’s try to do it in O(n) time. If we can, then we have the best solution.

Thought process

Given a list like [6, 1, 7, 0, 3, 5, 6], we can do a “waterfall”.

We start with a list like this

greaterThan = 0, greaterThan = 0, … greaterThan[7 (length of our array)] = 0

As we iterate through, we add to the elements we see. For example, we go through the array, and we see a 6, so we know there’s at least one element greater than or equal to 6. So, greaterThan += 1.

In the end, we have this: greaterThan = [1, 1, 0, 1, 0, 1, 2, 1]. However, it’s like a waterfall. The number of elements greater than or equal to 6 equals the number of elements = 6 + the number of elements greater than or equal to 7.

[1, 1, 0, 1, 0, 1, 2, 1] becomes
[7, 6, 5, 5, 4, 4, 3, 1]. Now, we do pretty much the same thing as before.

There are 7 elements greater than 0.
There are 6 elements ≥ 1
There are 5 elements ≥ 2
There are 5 elements ≥ 3
There are 4 elements ≥ 4. We’re done now.

Faster than that, we can see

There is 1 element ≥ 7.
There are 3 elements ≥ 6.
There are 4 elements ≥ 5.
There are 4 elements ≥ 4.

Code

def determine(array):
if array == []: #Edge case
return 0
greaterThan = [0 for i in range(len(array) + 1)]
for i in array:
greaterThan[min(len(array), i)] += 1

#waterfall
if greaterThan[-1] >= len(array):
return len(array)
for i in range(len(array) - 1, -1, -1):
greaterThan[i] += greaterThan[i+1]
if greaterThan[i] >= i:
return i