0

If I am given a list of integers/floats, how would I find the two closest numbers using sorting?

PythonSOS
  • 339
  • 5
  • 16

3 Answers3

1

Such a method will do what you want:

>>> def minDistance(lst):
    lst = sorted(lst)
    index = -1
    distance = max(lst) - min(lst)
    for i in range(len(lst)-1):
        if lst[i+1] - lst[i] < distance:
            distance = lst[i+1] - lst[i] 
            index = i
    for i in range(len(lst)-1):
        if lst[i+1] - lst[i] == distance:
            print lst[i],lst[i+1]

In the first for loop we find out the minimum distance, and in the second loop, we print all the pairs with this distance. Works as below:

>>> lst = (1,2,3,6,12,9,1.4,145,12,83,53,12,3.4,2,7.5)
>>> minDistance(lst)
2 2
12 12
12 12
>>> 
EbraHim
  • 2,279
  • 2
  • 16
  • 28
  • Why do you set the index to -1? – PythonSOS Apr 25 '16 at 17:32
  • @PythonSOS I just wanted to define the `index` variable for next usage. This initial value will not use anywhere. You can replace `-1` with any number. – EbraHim Apr 26 '16 at 02:04
  • also, will this work if there are two numbers in a list that are the exact same? like if I have [3,3,4], it should return [3,3] and not [3,4] – PythonSOS Apr 26 '16 at 23:25
  • @PythonSOS I'm not here to solve your homework. I'm here to help you! Try it yourself, if doesn't worked try to change it as you want and finally if you faced any error, ask us. – EbraHim Apr 27 '16 at 04:44
0

It could be more than one possibilities. Consider this list

[0,1, 20, 25, 30, 200, 201]

[0,1] and [200, 201] are equal closest.

Jose Hermosilla Rodrigo
  • 3,513
  • 6
  • 22
  • 38
0

Jose has a valid point. However, you could just consider these cases equal and not care about returning one or the other.

I don't think you need a sorting algorithm, per say, but maybe just a sort of 'champion' algorithm like this one:

def smallestDistance(self, arr):
    championI = -1
    championJ = -1
    champDistance = sys.maxint
    i = 0
    while i < arr.length:
        j = i + 1
        while j < arr.length:
            if math.fabs(arr[i] - arr[j]) < champDistance:
                championI = i
                championJ = j
                champDistance = math.fabs(arr[i] - arr[j])
            j += 1
        i += 1
    r = [arr[championI], arr[championJ]]
    return r

This function will return a sub array with the two values that are closest together. Note that this will only work given an array of at least two long. Otherwise, you will throw some error.

I think the popular sorting algorithm known as bubble sort would do this quite well. Though running at possible O(n^2) time if that kind of thing matters to you...

Here is standard bubble sort based on the sorting of arrays by integer size.

 def bubblesort( A ):
  for i in range( len( A ) ):
    for k in range( len( A ) - 1, i, -1 ):
      if ( A[k] < A[k - 1] ):
        swap( A, k, k - 1 )

def swap( A, x, y ):
  tmp = A[x]
  A[x] = A[y]
  A[y] = tmp

You can just modify the algorithm slightly to fit your purposes if you insist on doing this using a sorting algorithm. However, I think the initial function works as well...

hope that helps.

modesitt
  • 7,052
  • 2
  • 34
  • 64
  • would the second code, with only the first function work as well? i also need to do the same thing by using two nested for loops. – PythonSOS Apr 25 '16 at 15:39
  • It is just decomposed a bit @PythonSOS. You would need to change up the loops if you insist on a bubble sort approach. – modesitt Apr 26 '16 at 04:59