Skip to content

Commit 71e706c

Browse files
authored
Merge pull request #37 from miguelHx/miguel_2.1_remove_dups
Miguel 2.1 - Remove Dups [Python]
2 parents 516522f + f3ba3db commit 71e706c

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
"""
2+
Python version 3.7.0
3+
2.1 - Remove Dups
4+
Write code to remove duplicates
5+
from an unsorted linked list.
6+
How would you solve this if a temporary
7+
buffer is not allowed?
8+
"""
9+
import unittest
10+
11+
12+
class Node:
13+
def __init__(self, d: int):
14+
self.data = d
15+
self.next = None
16+
17+
18+
class LinkedList:
19+
def __init__(self, *numbers: int):
20+
self.head = None
21+
self.tail = None
22+
for num in numbers:
23+
self.append_to_tail(num)
24+
25+
def append_to_tail(self, d: int) -> None:
26+
if self.head is None:
27+
self.head = Node(d)
28+
self.tail = self.head
29+
return
30+
end = Node(d)
31+
self.tail.next = end
32+
self.tail = end
33+
34+
def append_to_head(self, d: int) -> None:
35+
new_head = Node(d)
36+
new_head.next = self.head
37+
self.head = new_head
38+
39+
def __repr__(self):
40+
return self.__str__()
41+
42+
def __str__(self):
43+
if self.head is None:
44+
return '<empty>'
45+
ll = []
46+
n = self.head
47+
while n.next is not None:
48+
ll.append('{} -> '.format(n.data))
49+
n = n.next
50+
ll.append(str(n.data))
51+
return ''.join(ll)
52+
53+
def __eq__(self, other: object):
54+
if not isinstance(other, LinkedList):
55+
return NotImplemented
56+
a = self.head
57+
b = other.head
58+
while a is not None and b is not None:
59+
if a.data != b.data:
60+
return False
61+
# otherwise, advance both pointers
62+
a = a.next
63+
b = b.next
64+
return a is None and b is None
65+
66+
67+
def remove_dups(ll: LinkedList) -> LinkedList:
68+
"""
69+
remove_dups will remove duplicates from the
70+
input linked list ll. A temporary buffer
71+
is used.
72+
Runtime: O(N)
73+
Space Complexity: O(N)
74+
:param ll: a linked list
75+
:return: a linked list without duplicates
76+
"""
77+
n = ll.head
78+
unique_vals = {n.data} # set literal
79+
output_ll = LinkedList(n.data)
80+
while n is not None:
81+
if n.data not in unique_vals:
82+
output_ll.append_to_tail(n.data)
83+
unique_vals.add(n.data)
84+
n = n.next
85+
return output_ll
86+
87+
88+
def remove_dups_no_buffer(ll: LinkedList) -> LinkedList:
89+
"""
90+
remove_dups will remove duplicates from the
91+
input linked list ll. No temporary buffer
92+
used.
93+
Runtime: O(N^2)
94+
Space Complexity: O(1)
95+
:param ll: a linked list
96+
:return: a linked list without duplicates
97+
"""
98+
n = ll.head
99+
while n is not None:
100+
curr_data = n.data
101+
m = n.next
102+
prev = n
103+
# search for duplicates from n + 1 to the
104+
# end of the linked list
105+
while m is not None:
106+
if m.data == curr_data:
107+
# re-arrange pointers to omit
108+
# the duplicate
109+
prev.next = m.next
110+
else:
111+
# otherwise, advance m and prev pointers
112+
prev = m
113+
m = prev.next
114+
n = n.next
115+
return ll
116+
117+
118+
class TestRemoveDups(unittest.TestCase):
119+
120+
def setUp(self):
121+
self.test_cases = [
122+
(
123+
LinkedList(1, 2, 3, 3, 5),
124+
LinkedList(1, 2, 3, 5)
125+
),
126+
(
127+
LinkedList(1, 2, 3, 3),
128+
LinkedList(1, 2, 3)
129+
),
130+
(
131+
LinkedList(1, 2, 2),
132+
LinkedList(1, 2)
133+
),
134+
(
135+
LinkedList(1),
136+
LinkedList(1)
137+
),
138+
(
139+
LinkedList(1, 1),
140+
LinkedList(1)
141+
),
142+
(
143+
LinkedList(2, 2, 2, 2, 2, 2),
144+
LinkedList(2)
145+
),
146+
(
147+
LinkedList(1, 1, 3, 4, 5, 5, 6, 7),
148+
LinkedList(1, 3, 4, 5, 6, 7)
149+
),
150+
(
151+
LinkedList(7, 2, 7, 9, 20, 1, 0, 0, 0, 25),
152+
LinkedList(7, 2, 9, 20, 1, 0, 25)
153+
),
154+
(
155+
LinkedList(9, 8, 7, 6, 6, 1, 2, 3, 4, 4),
156+
LinkedList(9, 8, 7, 6, 1, 2, 3, 4)
157+
),
158+
(
159+
LinkedList(9, 9, 9, -10, -100, 45, 67, -100, 99),
160+
LinkedList(9, -10, -100, 45, 67, 99)
161+
)
162+
]
163+
164+
def test_remove_dups(self):
165+
for ll, expected in self.test_cases:
166+
self.assertEqual(remove_dups(ll), expected)
167+
168+
def test_remove_dups_no_buffer(self):
169+
for ll, expected in self.test_cases:
170+
self.assertEqual(remove_dups_no_buffer(ll), expected)
171+
172+
173+
if __name__ == '__main__':
174+
unittest.main()

0 commit comments

Comments
 (0)