Skip to content

Commit f19f911

Browse files
committed
miguel soln to delete middle node 2.3
1 parent 8ad3fff commit f19f911

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"""
2+
Python version 3.7.0
3+
2.3 - Delete Middle Node
4+
Implement an algorithm to delete a node
5+
in the middle (i.e., any node but the
6+
first and last node, not necessarily
7+
the exact middle) of a singly linked list,
8+
given only access to that node
9+
EXAMPLE
10+
Input: the node c from the linked list
11+
a -> b -> c -> d -> e -> f
12+
Result: nothing is returned, but the new
13+
linked list looks like
14+
a -> b -> d -> e -> f
15+
"""
16+
import unittest
17+
18+
19+
class Node:
20+
def __init__(self, d: int):
21+
self.data = d
22+
self.next = None
23+
24+
def __repr__(self):
25+
return self.__str__()
26+
27+
def __str__(self):
28+
return '<Node Value: {}>'.format(self.data)
29+
30+
def __eq__(self, other: object):
31+
if not isinstance(other, Node):
32+
return NotImplemented
33+
return self.data == other.data
34+
35+
36+
class LinkedList:
37+
def __init__(self, *numbers: int):
38+
self.head = None
39+
self.tail = None
40+
self.size = 0
41+
for num in numbers:
42+
self.append_to_tail(num)
43+
44+
def append_to_tail(self, d: int) -> None:
45+
if self.head is None:
46+
self.head = Node(d)
47+
self.tail = self.head
48+
else:
49+
end = Node(d)
50+
self.tail.next = end
51+
self.tail = end
52+
self.size += 1
53+
54+
def append_to_head(self, d: int) -> None:
55+
new_head = Node(d)
56+
new_head.next = self.head
57+
self.head = new_head
58+
self.size += 1
59+
60+
def get_node_at(self, index: int):
61+
if index < 0 or index >= self.size:
62+
raise IndexError('list index out of range')
63+
n = self.head
64+
i = 0
65+
while n is not None:
66+
if i == index:
67+
return n
68+
i += 1
69+
n = n.next
70+
71+
def __repr__(self):
72+
return self.__str__()
73+
74+
def __str__(self):
75+
if self.head is None:
76+
return '<empty>'
77+
ll = []
78+
n = self.head
79+
while n.next is not None:
80+
ll.append('{} -> '.format(n.data))
81+
n = n.next
82+
ll.append(str(n.data))
83+
return ''.join(ll)
84+
85+
def __eq__(self, other: object):
86+
if not isinstance(other, LinkedList):
87+
return NotImplemented
88+
a = self.head
89+
b = other.head
90+
while a is not None and b is not None:
91+
if a.data != b.data:
92+
return False
93+
# otherwise, advance both pointers
94+
a = a.next
95+
b = b.next
96+
return a is None and b is None
97+
98+
99+
def delete_middle_node(ll: LinkedList, node: Node) -> LinkedList:
100+
"""
101+
delete_middle_node will delete a node from
102+
a singly linked list. The node can be any
103+
node within the linked list that is NOT the
104+
head or the tail.
105+
We will be comparing the address of
106+
the input node with the address of each
107+
node in the linked list.
108+
Runtime: O(N)
109+
Space Complexity: O(1)
110+
:param ll: an input linked list
111+
:param node: pointer to a node in ll
112+
:return: a linked list with/wo having deleted node
113+
"""
114+
if node is ll.head or node is ll.tail:
115+
raise ValueError('node cannot be head or tail of linked list')
116+
n = ll.head
117+
while n.next is not None:
118+
if n.next is node:
119+
n.next = n.next.next
120+
n = n.next
121+
return ll
122+
123+
124+
class TestDeleteMiddleNode(unittest.TestCase):
125+
126+
def setUp(self):
127+
self.test_cases = [
128+
(
129+
LinkedList(1, 2, 3, 4, 5, 6),
130+
2,
131+
LinkedList(1, 2, 4, 5, 6),
132+
),
133+
(
134+
LinkedList(3, 6, 2, 1, 7, 8),
135+
1,
136+
LinkedList(3, 2, 1, 7, 8),
137+
),
138+
(
139+
LinkedList(-100, 200, 65, 22, 1),
140+
3,
141+
LinkedList(-100, 200, 65, 1),
142+
)
143+
]
144+
145+
def test_delete_middle_node(self):
146+
for ll, node_index, expected in self.test_cases:
147+
result = delete_middle_node(ll, ll.get_node_at(node_index))
148+
self.assertEqual(result, expected, msg=(ll, node_index, expected))
149+
150+
def test_delete_middle_node_value_error(self):
151+
ll = LinkedList(1, 2, 3, 4)
152+
head = ll.head
153+
tail = ll.tail
154+
with self.assertRaises(ValueError, msg=(ll, ll.head)):
155+
delete_middle_node(ll, head)
156+
with self.assertRaises(ValueError, msg=(ll, ll.tail)):
157+
delete_middle_node(ll, tail)
158+
159+
160+
if __name__ == '__main__':
161+
unittest.main()

0 commit comments

Comments
 (0)