mirror of
https://github.com/donnemartin/interactive-coding-challenges.git
synced 2024-03-22 13:11:13 +08:00
Update quicksort challenge (#134)
Update constraints, test cases, code, algorithm, and tests.
This commit is contained in:
parent
a6881bab68
commit
3d49bb1d43
|
@ -34,9 +34,13 @@
|
|||
"source": [
|
||||
"## Constraints\n",
|
||||
"\n",
|
||||
"* Is a naiive solution sufficient (ie not in-place)?\n",
|
||||
"* Is a naive solution sufficient (ie not in-place)?\n",
|
||||
" * Yes\n",
|
||||
"* Are duplicates allowed?\n",
|
||||
" * Yes\n",
|
||||
"* Can we assume the input is valid?\n",
|
||||
" * No\n",
|
||||
"* Can we assume this fits memory?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
|
@ -46,7 +50,7 @@
|
|||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* None -> None\n",
|
||||
"* None -> Exception\n",
|
||||
"* Empty input -> []\n",
|
||||
"* One element -> [element]\n",
|
||||
"* Two or more elements"
|
||||
|
@ -76,9 +80,11 @@
|
|||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def quick_sort(data):\n",
|
||||
" # TODO: Implement me\n",
|
||||
" pass"
|
||||
"class QuickSort(object):\n",
|
||||
"\n",
|
||||
" def sort(self, data):\n",
|
||||
" # TODO: Implement me\n",
|
||||
" pass"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -101,37 +107,33 @@
|
|||
"outputs": [],
|
||||
"source": [
|
||||
"# %load test_quick_sort.py\n",
|
||||
"from nose.tools import assert_equal\n",
|
||||
"from nose.tools import assert_equal, assert_raises\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestQuickSort(object):\n",
|
||||
" def test_quick_sort(self, func):\n",
|
||||
"\n",
|
||||
" def test_quick_sort(self):\n",
|
||||
" quick_sort = QuickSort()\n",
|
||||
"\n",
|
||||
" print('None input')\n",
|
||||
" data = None\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, None)\n",
|
||||
" assert_raises(TypeError, quick_sort.sort, None)\n",
|
||||
"\n",
|
||||
" print('Empty input')\n",
|
||||
" data = []\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, [])\n",
|
||||
" assert_equal(quick_sort.sort([]), [])\n",
|
||||
"\n",
|
||||
" print('One element')\n",
|
||||
" data = [5]\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, [5])\n",
|
||||
" assert_equal(quick_sort.sort([5]), [5])\n",
|
||||
"\n",
|
||||
" print('Two or more elements')\n",
|
||||
" data = [5, 1, 7, 2, 6, -3, 5, 7, -1]\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, sorted(data))\n",
|
||||
" assert_equal(quick_sort.sort(data), sorted(data))\n",
|
||||
"\n",
|
||||
" print('Success: test_quick_sort\\n')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" test = TestQuickSort()\n",
|
||||
" test.test_quick_sort(quick_sort)\n",
|
||||
" test.test_quick_sort()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
|
|
|
@ -34,9 +34,13 @@
|
|||
"source": [
|
||||
"## Constraints\n",
|
||||
"\n",
|
||||
"* Is a naiive solution sufficient (ie not in-place)?\n",
|
||||
"* Is a naive solution sufficient (ie not in-place)?\n",
|
||||
" * Yes\n",
|
||||
"* Are duplicates allowed?\n",
|
||||
" * Yes\n",
|
||||
"* Can we assume the input is valid?\n",
|
||||
" * No\n",
|
||||
"* Can we assume this fits memory?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
|
@ -46,7 +50,7 @@
|
|||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* None -> None\n",
|
||||
"* None -> Exception\n",
|
||||
"* Empty input -> []\n",
|
||||
"* One element -> [element]\n",
|
||||
"* Two or more elements"
|
||||
|
@ -74,7 +78,16 @@
|
|||
"* Time: O(n log(n)) average, best, O(n^2) worst\n",
|
||||
"* Space: O(n+m), n = number of elements, m = recursion depth\n",
|
||||
"\n",
|
||||
"Most implementations are not stable."
|
||||
"Misc:\n",
|
||||
"\n",
|
||||
"* More sophisticated implementations are in-place, although they still take up recursion depth space\n",
|
||||
"* Most implementations are not stable\n",
|
||||
"\n",
|
||||
"See [Quicksort on wikipedia](https://en.wikipedia.org/wiki/Quicksort):\n",
|
||||
"\n",
|
||||
"Typically, quicksort is significantly faster in practice than other Θ(nlogn) algorithms, because its inner loop can be efficiently implemented on most architectures [presumably because it has good cache locality], and in most real-world data, it is possible to make design choices which minimize the probability of requiring quadratic time.\n",
|
||||
"\n",
|
||||
"See: [Quicksort vs merge sort](http://stackoverflow.com/questions/70402/why-is-quicksort-better-than-mergesort)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -95,28 +108,33 @@
|
|||
"from __future__ import division\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def quick_sort(data):\n",
|
||||
" if data is None or len(data) < 2:\n",
|
||||
" return data\n",
|
||||
" equal = []\n",
|
||||
" left = []\n",
|
||||
" right = []\n",
|
||||
" pivot_index = len(data) // 2\n",
|
||||
" pivot_value = data[pivot_index]\n",
|
||||
"class QuickSort(object):\n",
|
||||
"\n",
|
||||
" # Build the left and right partitions\n",
|
||||
" for i in range(len(data)):\n",
|
||||
" if data[i] == pivot_value:\n",
|
||||
" equal.append(data[i])\n",
|
||||
" elif data[i] < pivot_value:\n",
|
||||
" left.append(data[i])\n",
|
||||
" else:\n",
|
||||
" right.append(data[i])\n",
|
||||
" def sort(self, data):\n",
|
||||
" if data is None:\n",
|
||||
" raise TypeError('data cannot be None')\n",
|
||||
" return self._sort(data)\n",
|
||||
"\n",
|
||||
" # Recursively apply quick_sort\n",
|
||||
" left = quick_sort(left)\n",
|
||||
" right = quick_sort(right)\n",
|
||||
" return left + equal + right"
|
||||
" def _sort(self, data):\n",
|
||||
" if len(data) < 2:\n",
|
||||
" return data\n",
|
||||
" equal = []\n",
|
||||
" left = []\n",
|
||||
" right = []\n",
|
||||
" pivot_index = len(data) // 2\n",
|
||||
" pivot_value = data[pivot_index]\n",
|
||||
" # Build the left and right partitions\n",
|
||||
" for item in data:\n",
|
||||
" if item == pivot_value:\n",
|
||||
" equal.append(item)\n",
|
||||
" elif item < pivot_value:\n",
|
||||
" left.append(item)\n",
|
||||
" else:\n",
|
||||
" right.append(item)\n",
|
||||
" # Recursively apply quick_sort\n",
|
||||
" left_ = self._sort(left)\n",
|
||||
" right_ = self._sort(right)\n",
|
||||
" return left_ + equal + right_"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -144,37 +162,33 @@
|
|||
],
|
||||
"source": [
|
||||
"%%writefile test_quick_sort.py\n",
|
||||
"from nose.tools import assert_equal\n",
|
||||
"from nose.tools import assert_equal, assert_raises\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestQuickSort(object):\n",
|
||||
" def test_quick_sort(self, func):\n",
|
||||
"\n",
|
||||
" def test_quick_sort(self):\n",
|
||||
" quick_sort = QuickSort()\n",
|
||||
"\n",
|
||||
" print('None input')\n",
|
||||
" data = None\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, None)\n",
|
||||
" assert_raises(TypeError, quick_sort.sort, None)\n",
|
||||
"\n",
|
||||
" print('Empty input')\n",
|
||||
" data = []\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, [])\n",
|
||||
" assert_equal(quick_sort.sort([]), [])\n",
|
||||
"\n",
|
||||
" print('One element')\n",
|
||||
" data = [5]\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, [5])\n",
|
||||
" assert_equal(quick_sort.sort([5]), [5])\n",
|
||||
"\n",
|
||||
" print('Two or more elements')\n",
|
||||
" data = [5, 1, 7, 2, 6, -3, 5, 7, -1]\n",
|
||||
" sorted_data = func(data)\n",
|
||||
" assert_equal(sorted_data, sorted(data))\n",
|
||||
" assert_equal(quick_sort.sort(data), sorted(data))\n",
|
||||
"\n",
|
||||
" print('Success: test_quick_sort\\n')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" test = TestQuickSort()\n",
|
||||
" test.test_quick_sort(quick_sort)\n",
|
||||
" test.test_quick_sort()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
|
|
|
@ -1,34 +1,30 @@
|
|||
from nose.tools import assert_equal
|
||||
from nose.tools import assert_equal, assert_raises
|
||||
|
||||
|
||||
class TestQuickSort(object):
|
||||
def test_quick_sort(self, func):
|
||||
|
||||
def test_quick_sort(self):
|
||||
quick_sort = QuickSort()
|
||||
|
||||
print('None input')
|
||||
data = None
|
||||
sorted_data = func(data)
|
||||
assert_equal(sorted_data, None)
|
||||
assert_raises(TypeError, quick_sort.sort, None)
|
||||
|
||||
print('Empty input')
|
||||
data = []
|
||||
sorted_data = func(data)
|
||||
assert_equal(sorted_data, [])
|
||||
assert_equal(quick_sort.sort([]), [])
|
||||
|
||||
print('One element')
|
||||
data = [5]
|
||||
sorted_data = func(data)
|
||||
assert_equal(sorted_data, [5])
|
||||
assert_equal(quick_sort.sort([5]), [5])
|
||||
|
||||
print('Two or more elements')
|
||||
data = [5, 1, 7, 2, 6, -3, 5, 7, -1]
|
||||
sorted_data = func(data)
|
||||
assert_equal(sorted_data, sorted(data))
|
||||
assert_equal(quick_sort.sort(data), sorted(data))
|
||||
|
||||
print('Success: test_quick_sort\n')
|
||||
|
||||
|
||||
def main():
|
||||
test = TestQuickSort()
|
||||
test.test_quick_sort(quick_sort)
|
||||
test.test_quick_sort()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue
Block a user