mirror of
https://github.com/donnemartin/interactive-coding-challenges.git
synced 2024-03-22 13:11:13 +08:00
199 lines
5.2 KiB
Plaintext
199 lines
5.2 KiB
Plaintext
{
|
|
"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: Delete a node in the middle, given only access to that node.\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",
|
|
"* What if the final node is being deleted, for example a single node list? Do we make it a dummy with a NULL value?\n",
|
|
" * Yes\n",
|
|
"* Can we assume we already have a linked list class that can be used for this problem?\n",
|
|
" * Yes"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Test Cases\n",
|
|
"\n",
|
|
"* Empty list\n",
|
|
"* Null node to delete\n",
|
|
"* One node\n",
|
|
"* Multiple nodes"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Algorithm\n",
|
|
"\n",
|
|
"We'll need two pointers, one to the current node and one to the next node. We will copy the next node's data to the current node's data (effectively deleting the current node) and update the current node's next pointer.\n",
|
|
"\n",
|
|
"* Check for error cases listed above\n",
|
|
"* set curr.data to next.data\n",
|
|
"* set curr.next to next.next\n",
|
|
"\n",
|
|
"Complexity:\n",
|
|
"* Time: O(1)\n",
|
|
"* Space: In-place"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Code"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"%run linked_list.py"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Node(object):\n",
|
|
" def __init__(self, data):\n",
|
|
" self.data = data\n",
|
|
" self.next = None\n",
|
|
"\n",
|
|
"class MyLinkedList(LinkedList):\n",
|
|
" def delete_node(self, node):\n",
|
|
" if self.head is None:\n",
|
|
" return\n",
|
|
" if node is None:\n",
|
|
" return\n",
|
|
" node_next = node.next\n",
|
|
" if node_next is None:\n",
|
|
" node.data = None\n",
|
|
" node.next = None\n",
|
|
" else:\n",
|
|
" node.data = node_next.data\n",
|
|
" node.next = node_next.next"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Unit Test"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"*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 list, null node to delete\n",
|
|
"Test: One node\n",
|
|
"Test: Multiple nodes\n",
|
|
"Success: test_delete_node\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from nose.tools import assert_equal\n",
|
|
"\n",
|
|
"class Test(object):\n",
|
|
" def test_delete_node(self):\n",
|
|
" print('Test: Empty list, null node to delete')\n",
|
|
" linked_list = MyLinkedList(None)\n",
|
|
" linked_list.delete_node(None)\n",
|
|
" assert_equal(linked_list.get_all_data(), [])\n",
|
|
"\n",
|
|
" print('Test: One node')\n",
|
|
" head = Node(2)\n",
|
|
" linked_list = MyLinkedList(head)\n",
|
|
" linked_list.delete_node(head)\n",
|
|
" assert_equal(linked_list.get_all_data(), [None])\n",
|
|
"\n",
|
|
" print('Test: Multiple nodes')\n",
|
|
" linked_list = MyLinkedList(None) \n",
|
|
" node0 = linked_list.insert_to_front(1)\n",
|
|
" node1 = linked_list.insert_to_front(3)\n",
|
|
" node2 = linked_list.insert_to_front(4)\n",
|
|
" node3 = linked_list.insert_to_front(1)\n",
|
|
" linked_list.delete_node(node2)\n",
|
|
" assert_equal(linked_list.get_all_data(), [1, 3, 1])\n",
|
|
" \n",
|
|
" print('Success: test_delete_node')\n",
|
|
"\n",
|
|
"if __name__ == '__main__':\n",
|
|
" test = Test()\n",
|
|
" test.test_delete_node()"
|
|
]
|
|
}
|
|
],
|
|
"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
|
|
}
|