mirror of
https://github.com/donnemartin/interactive-coding-challenges
synced 2026-01-03 07:58:02 +00:00
Renamed top-level folders to use underscores instead of dashes.
This commit is contained in:
0
stacks_queues/__init__.py
Normal file
0
stacks_queues/__init__.py
Normal file
187
stacks_queues/hanoi.ipynb
Normal file
187
stacks_queues/hanoi.ipynb
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement the [Towers of Hanoi](http://en.wikipedia.org/wiki/Tower_of_Hanoi) with 3 towers and N disks.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* Can we assume we already have a stack class that can be used for this problem?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* NULL towers\n",
|
||||
"* 0 disks\n",
|
||||
"* 1 disk\n",
|
||||
"* 2 or more disks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"* Create three stacks to represent each tower\n",
|
||||
"* def hanoi(n, src, dest, buffer):\n",
|
||||
" * If 0 disks return\n",
|
||||
" * hanoi(n-1, src, buffer)\n",
|
||||
" * Move remaining element from src to dest\n",
|
||||
" * hanoi(n-1, buffer, dest) \n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(2^n)\n",
|
||||
"* Space: O(m) where m is the number of recursion levels"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hanoi(num_disks, src, dest, buff):\n",
|
||||
" if src is None or dest is None or buff is None:\n",
|
||||
" return\n",
|
||||
" if num_disks > 0:\n",
|
||||
" hanoi(num_disks-1, src, buff, dest)\n",
|
||||
" data = src.pop()\n",
|
||||
" dest.push(data)\n",
|
||||
" hanoi(num_disks-1, buff, dest, src)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: NULL towers\n",
|
||||
"Test: 0 disks\n",
|
||||
"Test: 1 disk\n",
|
||||
"Test: 2 or more disks\n",
|
||||
"Success: test_hanoi\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" def test_hanoi(self):\n",
|
||||
" num_disks = 3\n",
|
||||
" src = Stack()\n",
|
||||
" buff = Stack()\n",
|
||||
" dest = Stack()\n",
|
||||
"\n",
|
||||
" print('Test: NULL towers')\n",
|
||||
" hanoi(num_disks, None, None, None)\n",
|
||||
"\n",
|
||||
" print('Test: 0 disks')\n",
|
||||
" hanoi(num_disks, src, dest, buff)\n",
|
||||
" assert_equal(dest.pop(), None)\n",
|
||||
"\n",
|
||||
" print('Test: 1 disk')\n",
|
||||
" src.push(5)\n",
|
||||
" hanoi(num_disks, src, dest, buff)\n",
|
||||
" assert_equal(dest.pop(), 5)\n",
|
||||
"\n",
|
||||
" print('Test: 2 or more disks')\n",
|
||||
" for i in xrange(num_disks, -1, -1):\n",
|
||||
" src.push(i)\n",
|
||||
" hanoi(num_disks, src, dest, buff)\n",
|
||||
" for i in xrange(0, num_disks):\n",
|
||||
" assert_equal(dest.pop(), i)\n",
|
||||
"\n",
|
||||
" print('Success: test_hanoi')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_hanoi()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
227
stacks_queues/n-stacks.ipynb
Normal file
227
stacks_queues/n-stacks.ipynb
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement n stacks using a single array.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* Are the stacks and array a fixed size?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* Test the following on the three stacks:\n",
|
||||
" * Push to full stack\n",
|
||||
" * Push to non-full stack\n",
|
||||
" * Pop on empty stack\n",
|
||||
" * Pop on non-empty stack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"### Absolute Index\n",
|
||||
"\n",
|
||||
"* return stack size * stack index + stack pointer\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Push\n",
|
||||
"\n",
|
||||
"* If stack is full, throw exception\n",
|
||||
"* Else\n",
|
||||
" * Increment stack pointer\n",
|
||||
" * Get the absolute array index\n",
|
||||
" * Insert the value to this index\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Pop\n",
|
||||
"\n",
|
||||
"* If stack is empty, throw exception\n",
|
||||
"* Else\n",
|
||||
" * Store the value contained in the absolute array index\n",
|
||||
" * Set the value in the absolute array index to None\n",
|
||||
" * Decrement stack pointer\n",
|
||||
" * return value\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Stacks(object):\n",
|
||||
" def __init__(self, num_stacks, stack_size):\n",
|
||||
" self.num_stacks = num_stacks\n",
|
||||
" self.stack_size = stack_size\n",
|
||||
" self.stack_pointers = [-1] * num_stacks\n",
|
||||
" self.stack_array = [None] * num_stacks * stack_size\n",
|
||||
"\n",
|
||||
" def abs_index(self, stack_index):\n",
|
||||
" return stack_index * self.stack_size + self.stack_pointers[stack_index]\n",
|
||||
"\n",
|
||||
" def push(self, stack_index, data):\n",
|
||||
" if self.stack_pointers[stack_index] == self.stack_size - 1:\n",
|
||||
" raise Exception('Stack is full')\n",
|
||||
" else:\n",
|
||||
" self.stack_pointers[stack_index] += 1\n",
|
||||
" array_index = self.abs_index(stack_index)\n",
|
||||
" self.stack_array[array_index] = data\n",
|
||||
"\n",
|
||||
" def pop(self, stack_index):\n",
|
||||
" if self.stack_pointers[stack_index] == -1:\n",
|
||||
" raise Exception('Stack is empty')\n",
|
||||
" else:\n",
|
||||
" array_index = self.abs_index(stack_index) \n",
|
||||
" data = self.stack_array[array_index]\n",
|
||||
" self.stack_array[array_index] = None\n",
|
||||
" self.stack_pointers[stack_index] -= 1\n",
|
||||
" return data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Pop on empty stack\n",
|
||||
"Test: Push to full stack\n",
|
||||
"Test: Push to non-full stack\n",
|
||||
"Test: Pop on non-empty stack\n",
|
||||
"Success: test_stacks\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"from nose.tools import raises\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" @raises(Exception)\n",
|
||||
" def test_pop_on_empty(self, num_stacks, stack_size):\n",
|
||||
" print('Test: Pop on empty stack')\n",
|
||||
" stacks = Stacks(num_stacks, stack_size)\n",
|
||||
" stacks.pop(0)\n",
|
||||
"\n",
|
||||
" @raises(Exception)\n",
|
||||
" def test_push_on_full(self, num_stacks, stack_size):\n",
|
||||
" print('Test: Push to full stack')\n",
|
||||
" stacks = Stacks(num_stacks, stack_size)\n",
|
||||
" for i in xrange(0, stack_size):\n",
|
||||
" stacks.push(2, i)\n",
|
||||
" stacks.push(2, stack_size)\n",
|
||||
"\n",
|
||||
" def test_stacks(self, num_stacks, stack_size):\n",
|
||||
" print('Test: Push to non-full stack')\n",
|
||||
" stacks = Stacks(num_stacks, stack_size)\n",
|
||||
" stacks.push(0, 1)\n",
|
||||
" stacks.push(0, 2)\n",
|
||||
" stacks.push(1, 3)\n",
|
||||
" stacks.push(2, 4)\n",
|
||||
"\n",
|
||||
" print('Test: Pop on non-empty stack')\n",
|
||||
" assert_equal(stacks.pop(0), 2)\n",
|
||||
" assert_equal(stacks.pop(0), 1)\n",
|
||||
" assert_equal(stacks.pop(1), 3)\n",
|
||||
" assert_equal(stacks.pop(2), 4)\n",
|
||||
"\n",
|
||||
" print('Success: test_stacks\\n')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" num_stacks = 3\n",
|
||||
" stack_size = 100 \n",
|
||||
" test = Test()\n",
|
||||
" test.test_pop_on_empty(num_stacks, stack_size)\n",
|
||||
" test.test_push_on_full(num_stacks, stack_size)\n",
|
||||
" test.test_stacks(num_stacks, stack_size)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
226
stacks_queues/queue-from-stacks.ipynb
Normal file
226
stacks_queues/queue-from-stacks.ipynb
Normal file
@@ -0,0 +1,226 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement a queue using two stacks.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* Do you expect the methods to be enqueue and dequeue?\n",
|
||||
" * Yes\n",
|
||||
"* Can we assume we already have a stack class that can be used for this problem?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* Enqueue and dequeue on empty stack\n",
|
||||
"* Enqueue and dequeue on non-empty stack\n",
|
||||
"* Multiple enqueue in a row\n",
|
||||
"* Multiple dequeue in a row\n",
|
||||
"* Enqueue after a dequeue\n",
|
||||
"* Dequeue after an enqueue"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"We'll use two stacks (left and right) to implement the queue. The left stack will be used for enqueue and the right stack will be used for dequeue.\n",
|
||||
"\n",
|
||||
"To prevent multiple dequeue calls from needlessly shifting elements around between the stacks, we'll shift elements in a lazy manner.\n",
|
||||
"\n",
|
||||
"### Enqueue\n",
|
||||
"\n",
|
||||
"* If the left stack is empty and the right stack is not empty\n",
|
||||
" * Shift the elements of the right stack to the left stack\n",
|
||||
"* Push the data to the left stack\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(n)\n",
|
||||
"* Space: O(n)\n",
|
||||
"\n",
|
||||
"### Dequeue\n",
|
||||
"\n",
|
||||
"* If the right stack is empty and the the left stack is not empty\n",
|
||||
" * Shift the elements of the left stack to the right stack\n",
|
||||
"* Pop from the right stack and return the data\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(n)\n",
|
||||
"* Space: O(n)\n",
|
||||
"\n",
|
||||
"### Shift Stacks\n",
|
||||
"\n",
|
||||
"* While the source stack has elements:\n",
|
||||
" * Pop from the source stack and push the data to the destination stack\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(n)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class QueueFromStacks(object):\n",
|
||||
" def __init__(self):\n",
|
||||
" self.left_stack = Stack()\n",
|
||||
" self.right_stack = Stack()\n",
|
||||
"\n",
|
||||
" def shift_stacks(self, source, destination):\n",
|
||||
" while source.peek() is not None:\n",
|
||||
" destination.push(source.pop())\n",
|
||||
"\n",
|
||||
" def enqueue(self, data):\n",
|
||||
" if self.left_stack.is_empty() and not self.right_stack.is_empty():\n",
|
||||
" self.shift_stacks(self.right_stack, self.left_stack)\n",
|
||||
" self.left_stack.push(data)\n",
|
||||
"\n",
|
||||
" def dequeue(self):\n",
|
||||
" if self.right_stack.is_empty() and not self.left_stack.is_empty():\n",
|
||||
" self.shift_stacks(self.left_stack, self.right_stack)\n",
|
||||
" return self.right_stack.pop()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Dequeue on empty stack\n",
|
||||
"Test: Enqueue on empty stack\n",
|
||||
"Test: Enqueue on non-empty stack\n",
|
||||
"Test: Multiple enqueue in a row\n",
|
||||
"Test: Dequeue on non-empty stack\n",
|
||||
"Test: Dequeue after an enqueue\n",
|
||||
"Test: Multiple dequeue in a row\n",
|
||||
"Test: Enqueue after a dequeue\n",
|
||||
"Success: test_queue_from_stacks\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" def test_queue_from_stacks(self):\n",
|
||||
" print('Test: Dequeue on empty stack')\n",
|
||||
" queue = QueueFromStacks()\n",
|
||||
" assert_equal(queue.dequeue(), None)\n",
|
||||
"\n",
|
||||
" print('Test: Enqueue on empty stack')\n",
|
||||
" print('Test: Enqueue on non-empty stack')\n",
|
||||
" print('Test: Multiple enqueue in a row')\n",
|
||||
" num_items = 3\n",
|
||||
" for i in range (0, num_items):\n",
|
||||
" queue.enqueue(i)\n",
|
||||
"\n",
|
||||
" print('Test: Dequeue on non-empty stack')\n",
|
||||
" print('Test: Dequeue after an enqueue')\n",
|
||||
" assert_equal(queue.dequeue(), 0)\n",
|
||||
"\n",
|
||||
" print('Test: Multiple dequeue in a row')\n",
|
||||
" assert_equal(queue.dequeue(), 1)\n",
|
||||
" assert_equal(queue.dequeue(), 2)\n",
|
||||
"\n",
|
||||
" print('Test: Enqueue after a dequeue')\n",
|
||||
" queue.enqueue(5)\n",
|
||||
" assert_equal(queue.dequeue(), 5)\n",
|
||||
"\n",
|
||||
" print('Success: test_queue_from_stacks')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_queue_from_stacks()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
278
stacks_queues/queue-list.ipynb
Normal file
278
stacks_queues/queue-list.ipynb
Normal file
@@ -0,0 +1,278 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement a queue with enqueue and dequeue methods using a linked list.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)\n",
|
||||
"* [Pythonic-Code](#Pythonic-Code)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* If there is one item in the list, do you expect the first and last pointers to both point to it?\n",
|
||||
" * Yes\n",
|
||||
"* If there are no items on the list, do you expect the first and last pointers to be NULL?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"### Enqueue\n",
|
||||
"\n",
|
||||
"* Enqueue to an empty queue\n",
|
||||
"* Enqueue to a non-empty queue\n",
|
||||
"\n",
|
||||
"### Dequeue\n",
|
||||
"\n",
|
||||
"* Dequeue an empty queue\n",
|
||||
"* Dequeue a queue with one element\n",
|
||||
"* Dequeue a queue with more than one element"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"### Enqueue\n",
|
||||
"\n",
|
||||
"* If the list is empty, set first and last to node\n",
|
||||
"* Else, set last to node\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Dequeue\n",
|
||||
"\n",
|
||||
"* If the list is empty, return NULL\n",
|
||||
"* If the list has one node\n",
|
||||
" * Save the first node's value\n",
|
||||
" * Set first and last to NULL\n",
|
||||
" * Return the saved value\n",
|
||||
"* Else\n",
|
||||
" * Save the first node's value\n",
|
||||
" * Set first to its next node\n",
|
||||
" * Return the saved value\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Overwriting queue_list.py\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%writefile queue_list.py\n",
|
||||
"# Need to avoid naming this queue.py as it \n",
|
||||
"# will conflict with IPython Notebook\n",
|
||||
"\n",
|
||||
"class Node(object):\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self.data = data\n",
|
||||
" self.next = None\n",
|
||||
"\n",
|
||||
"class Queue(object):\n",
|
||||
" def __init__(self):\n",
|
||||
" self.first = None\n",
|
||||
" self.last = None\n",
|
||||
"\n",
|
||||
" def enqueue(self, data):\n",
|
||||
" node = Node(data)\n",
|
||||
" if self.first is None and self.last is None:\n",
|
||||
" self.first = node\n",
|
||||
" self.last = node\n",
|
||||
" else:\n",
|
||||
" self.last.next = node\n",
|
||||
" self.last = node\n",
|
||||
"\n",
|
||||
" def dequeue(self):\n",
|
||||
" # Empty list\n",
|
||||
" if self.first is None and self.last is None:\n",
|
||||
" return None\n",
|
||||
" \n",
|
||||
" # Remove only element from a one element list\n",
|
||||
" elif self.first == self.last:\n",
|
||||
" data = self.first.data\n",
|
||||
" self.first = None\n",
|
||||
" self.last = None\n",
|
||||
" return data\n",
|
||||
" else:\n",
|
||||
" data = self.first.data\n",
|
||||
" self.first = self.first.next\n",
|
||||
" return data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run queue_list.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Dequeue an empty queue\n",
|
||||
"Test: Enqueue to an empty queue\n",
|
||||
"Test: Dequeue a queue with one element\n",
|
||||
"Test: Enqueue to a non-empty queue\n",
|
||||
"Test: Dequeue a queue with more than one element\n",
|
||||
"Success: test_end_to_end\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" # TODO: It would be better if we had unit tests for each\n",
|
||||
" # method in addition to the following end-to-end test\n",
|
||||
" def test_end_to_end(self):\n",
|
||||
" print('Test: Dequeue an empty queue')\n",
|
||||
" queue = Queue()\n",
|
||||
" assert_equal(queue.dequeue(), None)\n",
|
||||
"\n",
|
||||
" print('Test: Enqueue to an empty queue')\n",
|
||||
" queue.enqueue(1)\n",
|
||||
"\n",
|
||||
" print('Test: Dequeue a queue with one element')\n",
|
||||
" assert_equal(queue.dequeue(), 1)\n",
|
||||
"\n",
|
||||
" print('Test: Enqueue to a non-empty queue')\n",
|
||||
" queue.enqueue(2)\n",
|
||||
" queue.enqueue(3)\n",
|
||||
" queue.enqueue(4)\n",
|
||||
"\n",
|
||||
" print('Test: Dequeue a queue with more than one element')\n",
|
||||
" assert_equal(queue.dequeue(), 2)\n",
|
||||
" assert_equal(queue.dequeue(), 3)\n",
|
||||
" assert_equal(queue.dequeue(), 4)\n",
|
||||
" \n",
|
||||
" print('Success: test_end_to_end')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_end_to_end()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Pythonic-Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Source: https://docs.python.org/2/tutorial/datastructures.html#using-lists-as-queues\n",
|
||||
"<pre>\n",
|
||||
"It is possible to use a list as a queue, where the first element added is the first element retrieved (“first-in, first-out”); however, lists are not efficient for this purpose. While appends and pops from the end of list are fast, doing inserts or pops from the beginning of a list is slow (because all of the other elements have to be shifted by one).\n",
|
||||
"\n",
|
||||
"To implement a queue, use collections.deque which was designed to have fast appends and pops from both ends. For example:\n",
|
||||
"\n",
|
||||
">>>\n",
|
||||
">>> from collections import deque\n",
|
||||
">>> queue = deque([\"Eric\", \"John\", \"Michael\"])\n",
|
||||
">>> queue.append(\"Terry\") # Terry arrives\n",
|
||||
">>> queue.append(\"Graham\") # Graham arrives\n",
|
||||
">>> queue.popleft() # The first to arrive now leaves\n",
|
||||
"'Eric'\n",
|
||||
">>> queue.popleft() # The second to arrive now leaves\n",
|
||||
"'John'\n",
|
||||
">>> queue # Remaining queue in order of arrival\n",
|
||||
"deque(['Michael', 'Terry', 'Graham'])\n",
|
||||
"</pre>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
36
stacks_queues/queue_list.py
Normal file
36
stacks_queues/queue_list.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Need to avoid naming this queue.py as it
|
||||
# will conflict with IPython Notebook
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.next = None
|
||||
|
||||
class Queue(object):
|
||||
def __init__(self):
|
||||
self.first = None
|
||||
self.last = None
|
||||
|
||||
def enqueue(self, data):
|
||||
node = Node(data)
|
||||
if self.first is None and self.last is None:
|
||||
self.first = node
|
||||
self.last = node
|
||||
else:
|
||||
self.last.next = node
|
||||
self.last = node
|
||||
|
||||
def dequeue(self):
|
||||
# Empty list
|
||||
if self.first is None and self.last is None:
|
||||
return None
|
||||
# Remove only element from a one element list
|
||||
elif self.first == self.last:
|
||||
data = self.first.data
|
||||
self.first = None
|
||||
self.last = None
|
||||
return data
|
||||
else:
|
||||
data = self.first.data
|
||||
self.first = self.first.next
|
||||
return data
|
||||
242
stacks_queues/set-of-stacks.ipynb
Normal file
242
stacks_queues/set-of-stacks.ipynb
Normal file
@@ -0,0 +1,242 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement SetOfStacks that wraps a list of stacks, where each stack is bound by a capacity.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* Can we assume we already have a stack class that can be used for this problem?\n",
|
||||
" * Yes\n",
|
||||
"* If a stack becomes full, we should automatically create one?\n",
|
||||
" * Yes\n",
|
||||
"* If a stack becomes empty, should we delete it?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* Push and pop on an empty stack\n",
|
||||
"* Push and pop on a non-empty stack\n",
|
||||
"* Push on a capacity stack to create a new one\n",
|
||||
"* Pop on a one element stack to destroy it"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"### Push\n",
|
||||
"\n",
|
||||
"* If there are no stacks or the last stack is full\n",
|
||||
" * Create a new stack\n",
|
||||
"* Push to the new stack\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Pop\n",
|
||||
"\n",
|
||||
"* If there are no stacks, return None\n",
|
||||
"* Else if the last stack has one element\n",
|
||||
" * Pop the last element's data\n",
|
||||
" * Delete the now empty stack\n",
|
||||
" * Update the last stack pointer\n",
|
||||
"* Else Pop the last element's data\n",
|
||||
"* Return the last element's data\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class StackWithCapacity(Stack):\n",
|
||||
" def __init__(self, top=None, capacity=10):\n",
|
||||
" self.capacity = capacity\n",
|
||||
" self.num_items = 0\n",
|
||||
" super(StackWithCapacity, self).__init__(top)\n",
|
||||
"\n",
|
||||
" def push(self, data):\n",
|
||||
" if self.num_items < self.capacity:\n",
|
||||
" super(StackWithCapacity, self).push(data)\n",
|
||||
" self.num_items += 1\n",
|
||||
" else:\n",
|
||||
" raise Exception('Stack full')\n",
|
||||
"\n",
|
||||
" def pop(self):\n",
|
||||
" data = super(StackWithCapacity, self).pop()\n",
|
||||
" self.num_items -= 1\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
" def is_full(self):\n",
|
||||
" return self.num_items == self.capacity\n",
|
||||
"\n",
|
||||
"class SetOfStacks(object):\n",
|
||||
" def __init__(self, capacity):\n",
|
||||
" self.capacity = capacity\n",
|
||||
" self.stacks = []\n",
|
||||
" self.last_stack = None\n",
|
||||
"\n",
|
||||
" def push(self, data):\n",
|
||||
" if self.last_stack is None or self.last_stack.is_full():\n",
|
||||
" self.last_stack = StackWithCapacity(None, self.capacity)\n",
|
||||
" self.stacks.append(self.last_stack)\n",
|
||||
" self.last_stack.push(data)\n",
|
||||
"\n",
|
||||
" def pop(self):\n",
|
||||
" if self.last_stack is None:\n",
|
||||
" return\n",
|
||||
" elif self.last_stack.top.next is None:\n",
|
||||
" data = self.last_stack.pop()\n",
|
||||
" self.stacks.pop()\n",
|
||||
" num_stacks = len(self.stacks)\n",
|
||||
" if num_stacks == 0:\n",
|
||||
" self.last_stack = None\n",
|
||||
" else:\n",
|
||||
" self.last_stack = self.stacks[num_stacks-1]\n",
|
||||
" else:\n",
|
||||
" data = self.last_stack.pop()\n",
|
||||
" return data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Push on an empty stack\n",
|
||||
"Test: Push on a non-empty stack\n",
|
||||
"Test: Push on a capacity stack to create a new one\n",
|
||||
"Test: Pop on a one element stack to destroy it\n",
|
||||
"Test: Pop general case\n",
|
||||
"Test: Pop on no elements\n",
|
||||
"Success: test_set_of_stacks\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" def test_set_of_stacks(self):\n",
|
||||
" print('Test: Push on an empty stack')\n",
|
||||
" capacity = 2\n",
|
||||
" stacks = SetOfStacks(capacity)\n",
|
||||
" stacks.push(3)\n",
|
||||
"\n",
|
||||
" print('Test: Push on a non-empty stack')\n",
|
||||
" stacks.push(5)\n",
|
||||
"\n",
|
||||
" print('Test: Push on a capacity stack to create a new one')\n",
|
||||
" stacks.push('a')\n",
|
||||
"\n",
|
||||
" print('Test: Pop on a one element stack to destroy it')\n",
|
||||
" assert_equal(stacks.pop(), 'a')\n",
|
||||
"\n",
|
||||
" print('Test: Pop general case')\n",
|
||||
" assert_equal(stacks.pop(), 5)\n",
|
||||
" assert_equal(stacks.pop(), 3)\n",
|
||||
"\n",
|
||||
" print('Test: Pop on no elements')\n",
|
||||
" assert_equal(stacks.pop(), None)\n",
|
||||
" \n",
|
||||
" print('Success: test_set_of_stacks')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_set_of_stacks()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
193
stacks_queues/sort-stack.ipynb
Normal file
193
stacks_queues/sort-stack.ipynb
Normal file
@@ -0,0 +1,193 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Sort a stack. You can use another stack as a buffer.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* When sorted, should the largest element be at the top or bottom?\n",
|
||||
" * Top\n",
|
||||
"* Can you have duplicate values like 5, 5?\n",
|
||||
" * Yes\n",
|
||||
"* Can we assume we already have a stack class that can be used for this problem?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* Empty stack\n",
|
||||
"* One element stack\n",
|
||||
"* Two or more element stack (general case)\n",
|
||||
"* Already sorted stack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"* Our buffer will hold elements in reverse sorted order, smallest at the top\n",
|
||||
"* Store the current top element in a temp variable\n",
|
||||
"* While stack is not empty\n",
|
||||
" * While buffer is empty or buffer top is > than temp\n",
|
||||
" * Move buffer top to stack\n",
|
||||
" * Move temp to top of buffer\n",
|
||||
"* Return buffer\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(n^2)\n",
|
||||
"* Space: O(n)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class MyStack(Stack):\n",
|
||||
" def sort(self):\n",
|
||||
" buff = MyStack()\n",
|
||||
" while not self.is_empty():\n",
|
||||
" temp = self.pop()\n",
|
||||
" while not buff.is_empty() and buff.peek() > temp:\n",
|
||||
" self.push(buff.pop())\n",
|
||||
" buff.push(temp)\n",
|
||||
" return buff"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Empty stack\n",
|
||||
"Test: One element stack\n",
|
||||
"Test: Two or more element stack (general case)\n",
|
||||
"Success: test_sort_stack\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from random import randint\n",
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" def get_sorted_stack(self, numbers):\n",
|
||||
" stack = MyStack()\n",
|
||||
" for x in numbers:\n",
|
||||
" stack.push(x)\n",
|
||||
" sorted_stack = stack.sort()\n",
|
||||
" return sorted_stack\n",
|
||||
"\n",
|
||||
" def test_sort_stack(self):\n",
|
||||
" print('Test: Empty stack')\n",
|
||||
" sorted_stack = self.get_sorted_stack([])\n",
|
||||
" assert_equal(sorted_stack.pop(), None)\n",
|
||||
"\n",
|
||||
" print('Test: One element stack')\n",
|
||||
" sorted_stack = self.get_sorted_stack([1])\n",
|
||||
" assert_equal(sorted_stack.pop(), 1)\n",
|
||||
"\n",
|
||||
" print('Test: Two or more element stack (general case)')\n",
|
||||
" num_items = 10\n",
|
||||
" numbers = [randint(0, 10) for x in xrange(num_items)]\n",
|
||||
" sorted_stack = self.get_sorted_stack(numbers)\n",
|
||||
" sorted_numbers = []\n",
|
||||
" for _ in xrange(num_items):\n",
|
||||
" sorted_numbers.append(sorted_stack.pop())\n",
|
||||
" assert_equal(sorted_numbers, sorted(numbers, reverse=True))\n",
|
||||
" \n",
|
||||
" print('Success: test_sort_stack')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_sort_stack()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
226
stacks_queues/stack-min.ipynb
Normal file
226
stacks_queues/stack-min.ipynb
Normal file
@@ -0,0 +1,226 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement a stack with push, pop, and min methods running O(1) time.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* Can we assume this is a stack of ints?\n",
|
||||
" * Yes\n",
|
||||
"* Can we assume we already have a stack class that can be used for this problem?\n",
|
||||
" * Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"* Push/pop on empty stack\n",
|
||||
"* Push/pop on non-empty stack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"We'll use a second stack to keep track of the minimum values.\n",
|
||||
"\n",
|
||||
"### Min\n",
|
||||
"\n",
|
||||
"* If the second stack is empty, return an error code (max int value)\n",
|
||||
"* Else, return the top of the stack, without popping it\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Push\n",
|
||||
"\n",
|
||||
"* Push the data\n",
|
||||
"* If the data is less than min\n",
|
||||
" * Push data to second stack\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(n)\n",
|
||||
"\n",
|
||||
"### Pop\n",
|
||||
"\n",
|
||||
"* Pop the data\n",
|
||||
"* If the data is equal to min\n",
|
||||
" * Pop the top of the second stack\n",
|
||||
"* Return the data\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"class MyStack(Stack):\n",
|
||||
" def __init__(self, top=None):\n",
|
||||
" self.min_vals = Stack()\n",
|
||||
" super(MyStack, self).__init__(top)\n",
|
||||
"\n",
|
||||
" def min(self):\n",
|
||||
" if self.min_vals.top is None:\n",
|
||||
" return sys.maxint\n",
|
||||
" else:\n",
|
||||
" return self.min_vals.peek()\n",
|
||||
"\n",
|
||||
" def push(self, data):\n",
|
||||
" super(MyStack, self).push(data)\n",
|
||||
" if data < self.min():\n",
|
||||
" self.min_vals.push(data)\n",
|
||||
"\n",
|
||||
" def pop(self):\n",
|
||||
" data = super(MyStack, self).pop()\n",
|
||||
" if data == self.min():\n",
|
||||
" self.min_vals.pop()\n",
|
||||
" return data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Push on empty stack, non-empty stack\n",
|
||||
"Test: Pop on non-empty stack\n",
|
||||
"Test: Pop empty stack\n",
|
||||
"Success: test_stack_min\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" def test_stack_min(self):\n",
|
||||
" print('Test: Push on empty stack, non-empty stack')\n",
|
||||
" stack = MyStack()\n",
|
||||
" stack.push(5)\n",
|
||||
" assert_equal(stack.peek(), 5)\n",
|
||||
" assert_equal(stack.min(), 5)\n",
|
||||
" stack.push(1)\n",
|
||||
" assert_equal(stack.peek(), 1)\n",
|
||||
" assert_equal(stack.min(), 1)\n",
|
||||
" stack.push(3)\n",
|
||||
" assert_equal(stack.peek(), 3)\n",
|
||||
" assert_equal(stack.min(), 1)\n",
|
||||
" stack.push(0)\n",
|
||||
" assert_equal(stack.peek(), 0)\n",
|
||||
" assert_equal(stack.min(), 0)\n",
|
||||
"\n",
|
||||
" print('Test: Pop on non-empty stack')\n",
|
||||
" assert_equal(stack.pop(), 0)\n",
|
||||
" assert_equal(stack.min(), 1)\n",
|
||||
" assert_equal(stack.pop(), 3)\n",
|
||||
" assert_equal(stack.min(), 1)\n",
|
||||
" assert_equal(stack.pop(), 1)\n",
|
||||
" assert_equal(stack.min(), 5)\n",
|
||||
" assert_equal(stack.pop(), 5)\n",
|
||||
" assert_equal(stack.min(), sys.maxint)\n",
|
||||
"\n",
|
||||
" print('Test: Pop empty stack')\n",
|
||||
" assert_equal(stack.pop(), None)\n",
|
||||
" \n",
|
||||
" print('Success: test_stack_min')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_stack_min()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
297
stacks_queues/stack.ipynb
Normal file
297
stacks_queues/stack.ipynb
Normal file
@@ -0,0 +1,297 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<small><i>This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes).</i></small>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Problem: Implement a stack with push, pop, peek, and is_empty methods using a linked list.\n",
|
||||
"\n",
|
||||
"* [Constraints and Assumptions](#Constraints-and-Assumptions)\n",
|
||||
"* [Test Cases](#Test-Cases)\n",
|
||||
"* [Algorithm](#Algorithm)\n",
|
||||
"* [Code](#Code)\n",
|
||||
"* [Unit Test](#Unit-Test)\n",
|
||||
"* [Pythonic-Code](#Pythonic-Code)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Constraints and Assumptions\n",
|
||||
"\n",
|
||||
"*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n",
|
||||
"\n",
|
||||
"* None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Test Cases\n",
|
||||
"\n",
|
||||
"### Push\n",
|
||||
"\n",
|
||||
"* Push to empty stack\n",
|
||||
"* Push to non-empty stack\n",
|
||||
"\n",
|
||||
"### Pop\n",
|
||||
"\n",
|
||||
"* Pop on empty stack\n",
|
||||
"* Pop on single element stack\n",
|
||||
"* Pop on multiple element stack\n",
|
||||
"\n",
|
||||
"### Peek\n",
|
||||
"\n",
|
||||
"* Peek on empty stack\n",
|
||||
"* Peek on one or more element stack\n",
|
||||
"\n",
|
||||
"### Is Empty\n",
|
||||
"\n",
|
||||
"* Is empty on empty stack\n",
|
||||
"* Is empty on one or more element stack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Algorithm\n",
|
||||
"\n",
|
||||
"### Push\n",
|
||||
"\n",
|
||||
"* Create new node with value\n",
|
||||
"* Set node's next to top\n",
|
||||
"* Set top to node\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Pop\n",
|
||||
"\n",
|
||||
"* If stack is empty, return NULL\n",
|
||||
"* Else \n",
|
||||
" * Save top's value\n",
|
||||
" * Set top to top.next\n",
|
||||
" * Return saved value\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Peek\n",
|
||||
"\n",
|
||||
"* If stack is empty, return NULL\n",
|
||||
"* Else return top's value\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)\n",
|
||||
"\n",
|
||||
"### Is Empty\n",
|
||||
"* If peek has a value, return False\n",
|
||||
"* Else return True\n",
|
||||
"\n",
|
||||
"Complexity:\n",
|
||||
"* Time: O(1)\n",
|
||||
"* Space: O(1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Overwriting stack.py\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%writefile stack.py\n",
|
||||
"\n",
|
||||
"class Node(object):\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self.data = data\n",
|
||||
" self.next = None\n",
|
||||
"\n",
|
||||
"class Stack(object):\n",
|
||||
" def __init__(self, top=None):\n",
|
||||
" self.top = top\n",
|
||||
"\n",
|
||||
" def push(self, data):\n",
|
||||
" node = Node(data)\n",
|
||||
" node.next = self.top\n",
|
||||
" self.top = node\n",
|
||||
"\n",
|
||||
" def pop(self):\n",
|
||||
" if self.top is not None:\n",
|
||||
" data = self.top.data\n",
|
||||
" self.top = self.top.next\n",
|
||||
" return data\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
" def peek(self):\n",
|
||||
" if self.top is not None:\n",
|
||||
" return self.top.data\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
" def is_empty(self):\n",
|
||||
" return self.peek() is None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%run stack.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Unit Test\n",
|
||||
"\n",
|
||||
"*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Test: Empty stack\n",
|
||||
"Test: One element\n",
|
||||
"Test: More than one element\n",
|
||||
"Success: test_end_to_end\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from nose.tools import assert_equal\n",
|
||||
"\n",
|
||||
"class Test(object):\n",
|
||||
" # TODO: It would be better if we had unit tests for each\n",
|
||||
" # method in addition to the following end-to-end test\n",
|
||||
" def test_end_to_end(self):\n",
|
||||
" print('Test: Empty stack')\n",
|
||||
" stack = Stack()\n",
|
||||
" assert_equal(stack.peek(), None)\n",
|
||||
" assert_equal(stack.pop(), None)\n",
|
||||
"\n",
|
||||
" print('Test: One element')\n",
|
||||
" top = Node(5)\n",
|
||||
" stack = Stack(top)\n",
|
||||
" assert_equal(stack.pop(), 5)\n",
|
||||
" assert_equal(stack.peek(), None)\n",
|
||||
"\n",
|
||||
" print('Test: More than one element')\n",
|
||||
" stack = Stack()\n",
|
||||
" stack.push(1)\n",
|
||||
" stack.push(2)\n",
|
||||
" stack.push(3)\n",
|
||||
" assert_equal(stack.pop(), 3)\n",
|
||||
" assert_equal(stack.peek(), 2)\n",
|
||||
" assert_equal(stack.pop(), 2)\n",
|
||||
" assert_equal(stack.peek(), 1)\n",
|
||||
" assert_equal(stack.is_empty(), False)\n",
|
||||
" assert_equal(stack.pop(), 1)\n",
|
||||
" assert_equal(stack.peek(), None)\n",
|
||||
" assert_equal(stack.is_empty(), True)\n",
|
||||
" \n",
|
||||
" print('Success: test_end_to_end')\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" test = Test()\n",
|
||||
" test.test_end_to_end()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Pythonic-Code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Source: https://docs.python.org/2/tutorial/datastructures.html#using-lists-as-stacks\n",
|
||||
"<pre>\n",
|
||||
"5.1.1. Using Lists as Stacks\n",
|
||||
"The list methods make it very easy to use a list as a stack, where the last element added is the first element retrieved (“last-in, first-out”). To add an item to the top of the stack, use append(). To retrieve an item from the top of the stack, use pop() without an explicit index. For example:\n",
|
||||
"\n",
|
||||
">>> stack = [3, 4, 5]\n",
|
||||
">>> stack.append(6)\n",
|
||||
">>> stack.append(7)\n",
|
||||
">>> stack\n",
|
||||
"[3, 4, 5, 6, 7]\n",
|
||||
">>> stack.pop()\n",
|
||||
"7\n",
|
||||
">>> stack\n",
|
||||
"[3, 4, 5, 6]\n",
|
||||
">>> stack.pop()\n",
|
||||
"6\n",
|
||||
">>> stack.pop()\n",
|
||||
"5\n",
|
||||
">>> stack\n",
|
||||
"[3, 4]\n",
|
||||
"</pre>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
29
stacks_queues/stack.py
Normal file
29
stacks_queues/stack.py
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.next = None
|
||||
|
||||
class Stack(object):
|
||||
def __init__(self, top=None):
|
||||
self.top = top
|
||||
|
||||
def push(self, data):
|
||||
node = Node(data)
|
||||
node.next = self.top
|
||||
self.top = node
|
||||
|
||||
def pop(self):
|
||||
if self.top is not None:
|
||||
data = self.top.data
|
||||
self.top = self.top.next
|
||||
return data
|
||||
return None
|
||||
|
||||
def peek(self):
|
||||
if self.top is not None:
|
||||
return self.top.data
|
||||
return None
|
||||
|
||||
def is_empty(self):
|
||||
return self.peek() is None
|
||||
0
stacks_queues/tests/__init__.py
Normal file
0
stacks_queues/tests/__init__.py
Normal file
Reference in New Issue
Block a user