Skip to content

Commit 516522f

Browse files
authored
Merge pull request #38 from miguelHx/miguel_2.2_return_kth_to_last
Miguel 2.2 - Kth To Last [Python]
2 parents eaa735f + 33bcca6 commit 516522f

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""
2+
Python version 3.7.0
3+
2.2 - Return Kth to Last
4+
Implement an algorithm to find the kth
5+
to last element of a singly linked list
6+
Example:
7+
input: ll = a -> b -> c -> d -> e -> f
8+
k = 3
9+
output: d because d is 3rd to last
10+
"""
11+
import unittest
12+
13+
14+
class Node:
15+
def __init__(self, d: int):
16+
self.data = d
17+
self.next = None
18+
19+
def __repr__(self):
20+
return self.__str__()
21+
22+
def __str__(self):
23+
return '<Node Value: {}>'.format(self.data)
24+
25+
def __eq__(self, other: object):
26+
if not isinstance(other, Node):
27+
return NotImplemented
28+
return self.data == other.data
29+
30+
31+
class LinkedList:
32+
def __init__(self, *numbers: int):
33+
self.head = None
34+
self.tail = None
35+
self.size = 0
36+
for num in numbers:
37+
self.append_to_tail(num)
38+
39+
def append_to_tail(self, d: int) -> None:
40+
if self.head is None:
41+
self.head = Node(d)
42+
self.tail = self.head
43+
else:
44+
end = Node(d)
45+
self.tail.next = end
46+
self.tail = end
47+
self.size += 1
48+
49+
def append_to_head(self, d: int) -> None:
50+
new_head = Node(d)
51+
new_head.next = self.head
52+
self.head = new_head
53+
self.size += 1
54+
55+
def __repr__(self):
56+
return self.__str__()
57+
58+
def __str__(self):
59+
if self.head is None:
60+
return '<empty>'
61+
ll = []
62+
n = self.head
63+
while n.next is not None:
64+
ll.append('{} -> '.format(n.data))
65+
n = n.next
66+
ll.append(str(n.data))
67+
return ''.join(ll)
68+
69+
def __eq__(self, other: object):
70+
if not isinstance(other, LinkedList):
71+
return NotImplemented
72+
a = self.head
73+
b = other.head
74+
while a is not None and b is not None:
75+
if a.data != b.data:
76+
return False
77+
# otherwise, advance both pointers
78+
a = a.next
79+
b = b.next
80+
return a is None and b is None
81+
82+
83+
def kth_to_last(ll: LinkedList, k: int) -> Node:
84+
"""
85+
kth_to_last will return the kth to last node
86+
from the input linked list.
87+
Going to reverse the linked list and then
88+
count k steps.
89+
Runtime: O(N)
90+
Space Complexity: O(1)
91+
:param ll: a linked list
92+
:param k:
93+
an integer where k > 0 and k < ll size
94+
:return:
95+
kth to last Node from the linked list
96+
or None
97+
"""
98+
if k <= 0 or k > ll.size:
99+
raise IndexError('list index out of range')
100+
# go size - k steps
101+
n = ll.head
102+
for i in range(1, ll.size - k + 1):
103+
n = n.next
104+
return n
105+
106+
107+
class TestKthToLast(unittest.TestCase):
108+
109+
def test_kth_to_last(self):
110+
l = list(range(1, 6))
111+
ll = LinkedList(*l)
112+
for k in range(1, len(l)):
113+
self.assertEqual(kth_to_last(ll, k), Node(l[-k]), msg=(ll, l[-k]))
114+
115+
def test_kth_to_last_index_error(self):
116+
k_values = [-1, 7, 0]
117+
ll = LinkedList(1, 2, 3)
118+
for k in k_values:
119+
with self.assertRaises(IndexError, msg=(ll, k)):
120+
kth_to_last(ll, k)
121+
122+
123+
if __name__ == '__main__':
124+
unittest.main()

0 commit comments

Comments
 (0)