This exercise is from Roughgarden's (excellent) course on algorithms on Coursera:
You are given as input an unsorted array of n distinct numbers, where n is a power of 2. Give an algorithm that identifies the second-largest number in the array, and that uses at most \$n + \log_2(n) - 2 \$ comparisons.
Note that it doesn't ask just ask to solve the problem in linear time. If we use \$2 n\$ comparisons the "big-O" time complexity would be linear but greater than \$n + \log_2(n) - 2\$.
Any feedback on the algorithm, implementation, style, and Python is very welcome.
import random
import sys
from math import log
count = 0
def is_greater(a, b):
global count
count += 1
return a > b
def _get_highest_two(arr0, arr1):
if is_greater(arr0[0], arr1[0]):
first = arr0[0]
seconds = arr0[1]
seconds.append(arr1[0])
else:
first = arr1[0]
seconds = arr1[1]
seconds.append(arr0[0])
return (first, seconds)
def get_second(*args):
if len(args) == 1:
seconds = args[0][1]
second_best = seconds.pop()
for sb in seconds:
if is_greater(sb, second_best):
second_best = sb
return second_best
_pairs = zip(*[iter(args)]*2)
_out = [_get_highest_two(*p) for p in _pairs]
return get_second(*_out)
def main():
n = int(sys.argv[1])
arr = [random.randint(0,100000000) for _ in xrange(n)]
print arr
print n, sorted(arr)[-2]
print count
# is_greater(0,0)
_pairs = zip(*[iter(arr)]*2)
_pairs = [(a, [b]) if is_greater(a, b) else (b, [a]) for (a, b) in _pairs]
print get_second(*_pairs)
print count, n + log(n, 2) - 2
return 0
if __name__ == '__main__':
sys.exit(main())