This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges).

Solution Notebook

Problem: Implement selection sort.

Constraints

  • Is a naiive solution sufficient (ie not stable, not based on a heap)?
    • Yes

Test Cases

  • Empty input -> []
  • One element -> [element]
  • Two or more elements

Algorithm

Wikipedia's animation:

We can do this recursively or iteratively. Iteratively will be more efficient as it doesn't require the extra space overhead with the recursive calls.

  • For each element
    • Check every element to the right to find the min
    • If min < current element, swap

Complexity:

  • Time: O(n^2) average, worst, best
  • Space: O(1) iterative, O(n) recursive (unless tail-call elimination is available, then O(1)), generally not stable

Code


In [1]:
def find_min_index(data, start):
    min_index = start
    for i in range(start + 1, len(data)):
        if data[i] < data[min_index]:
            min_index = i
    return min_index


def swap(data, i, j):
    if (i != j):
        data[i], data[j] = data[j], data[i]

In [2]:
def selection_sort(data, start=0):
    if start < len(data) - 1:
        swap(data, start, find_min_index(data, start))
        selection_sort(data, start+1)

In [3]:
def selection_sort_iterative(data):
    if len(data) == 0 or len(data) == 1:
        return
    for i in range(0, len(data) - 1):
        swap(data, i, find_min_index(data, i))

Unit Test


In [4]:
%%writefile test_selection_sort.py
from nose.tools import assert_equal


class TestSelectionSort(object):

    def test_selection_sort(self, func):
        print('Empty input')
        data = []
        func(data)
        assert_equal(data, [])

        print('One element')
        data = [5]
        func(data)
        assert_equal(data, [5])

        print('Two or more elements')
        data = [5, 1, 7, 2, 6, -3, 5, 7, -1]
        func(data)
        assert_equal(data, sorted(data))

        print('Success: test_selection_sort\n')


def main():
    test = TestSelectionSort()
    test.test_selection_sort(selection_sort)
    try:
        test.test_selection_sort(selection_sort_iterative)
    except NameError:
        # Alternate solutions are only defined
        # in the solutions file
        pass


if __name__ == '__main__':
    main()


Overwriting test_selection_sort.py

In [5]:
%run -i test_selection_sort.py


Empty input
One element
Two or more elements
Success: test_selection_sort

Empty input
One element
Two or more elements
Success: test_selection_sort