Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding N closest numbers

Have a 2-dimensional array, like -

a[0] = [ 0 , 4 , 9 ]
a[1] = [ 2 , 6 , 11 ]
a[2] = [ 3 , 8 , 13 ]
a[3] = [ 7 , 12 ]

Need to select one element from each of the sub-array in a way that the resultant set of numbers are closest, that is the difference between the highest number and lowest number in the set is minimum.

The answer to the above will be = [ 9 , 6 , 8 , 7 ].

Have made an algorithm, but don't feel its a good one. What would be a efficient algorithm to do this in terms of time and space complexity?

EDIT - My Algorithm (in python)-

INPUT - Dictionary : table{}
OUTPUT - Dictionary : low_table{}
#
N = len(table)
for word_key in table:
    for init in table[word_key]:
        temp_table = copy.copy(table)
        del temp_table[word_key]
        per_init = copy.copy(init)
        low_table[init]=[]
        for ite in range(N-1):
            min_val = 9999
            for i in temp_table:
                for nums in temp_table[i]:
                    if min_val > abs(init-nums):
                        min_val = abs(init-nums)
                        del_num = i
                        next_num = nums
            low_table[per_init].append(next_num)
            init = (init+next_num)/2
            del temp_table[del_num]
lowest_val = 99
lowest_set = []
for x in low_table:
    low_table[x].append(x)
    low_table[x].sort()
    mini = low_table[x][-1]-low_table[x][0]
    if mini < lowest_val:
        lowest_val = mini
        lowest_set = low_table[x]
print lowest_set
like image 723
Anirudh Avatar asked Jul 16 '13 02:07

Anirudh


1 Answers

collect all the values to create a single ordered sequence, with each element tagged with the array it came from: 0(0), 2(1), 3(2), 4(0), 6(1), ... 12(3), 13(2)

then create a window across them, starting with the first (0(0)) and ending it at the first position that makes the window span all the arrays (0(0) -> 7(3))

then roll this window by incrementing the start of the window by one, and increment the end of the window until you again have a window that covers all elements.

then roll it again: (2(1), 3(2), 4(0), ... 7(3)), and so forth.

at each step keep track of the the difference between the largest and the smallest. Eventually you find the one with the smallest window. I have the feeling that in the worst case this is O(n^2) but that's just a guess.

like image 155
whiterook6 Avatar answered Oct 18 '22 23:10

whiterook6