Skip to content

Commit b59e859

Browse files
authored
Add find kth_element_from_end in linked_lists (#13322)
* Add find kth_element_from_end in linked-lists * Update kth_element_from_end docstring * Update kth_element_from_end k to position
1 parent 1429eec commit b59e859

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
from typing import Any
5+
6+
7+
@dataclass
8+
class Node:
9+
item: Any
10+
next: Node | Any = None
11+
12+
13+
class LinkedList:
14+
def __init__(self) -> None:
15+
self.head: Node | None = None
16+
self.size = 0
17+
18+
def __str__(self) -> str:
19+
"""
20+
>>> linked_list = LinkedList()
21+
>>> linked_list.add(23)
22+
>>> linked_list.add(14)
23+
>>> linked_list.add(9)
24+
>>> print(linked_list)
25+
9 --> 14 --> 23
26+
"""
27+
iterate = self.head
28+
item_str = ""
29+
item_list: list[str] = []
30+
while iterate:
31+
item_list.append(str(iterate.item))
32+
iterate = iterate.next
33+
34+
item_str = " --> ".join(item_list)
35+
36+
return item_str
37+
38+
def __len__(self) -> int:
39+
"""
40+
>>> linked_list = LinkedList()
41+
>>> len(linked_list)
42+
0
43+
>>> linked_list.add("a")
44+
>>> len(linked_list)
45+
1
46+
>>> linked_list.add("b")
47+
>>> len(linked_list)
48+
2
49+
"""
50+
return self.size
51+
52+
def add(self, item: Any, position: int = 0) -> None:
53+
"""
54+
Add an item to the LinkedList at the specified position.
55+
Default position is 0 (the head).
56+
57+
Args:
58+
item (Any): The item to add to the LinkedList.
59+
position (int, optional): The position at which to add the item.
60+
Defaults to 0.
61+
62+
Raises:
63+
ValueError: If the position is negative or out of bounds.
64+
65+
>>> linked_list = LinkedList()
66+
>>> linked_list.add(1)
67+
>>> linked_list.add(2)
68+
>>> linked_list.add(3)
69+
>>> linked_list.add(4, 2)
70+
>>> print(linked_list)
71+
3 --> 2 --> 4 --> 1
72+
73+
# Test adding to a negative position
74+
>>> linked_list.add(5, -3)
75+
Traceback (most recent call last):
76+
...
77+
ValueError: Position must be non-negative
78+
79+
# Test adding to an out-of-bounds position
80+
>>> linked_list.add(5,7)
81+
Traceback (most recent call last):
82+
...
83+
ValueError: Out of bounds
84+
>>> linked_list.add(5, 4)
85+
>>> print(linked_list)
86+
3 --> 2 --> 4 --> 1 --> 5
87+
"""
88+
if position < 0:
89+
raise ValueError("Position must be non-negative")
90+
91+
if position == 0 or self.head is None:
92+
new_node = Node(item, self.head)
93+
self.head = new_node
94+
else:
95+
current = self.head
96+
for _ in range(position - 1):
97+
current = current.next
98+
if current is None:
99+
raise ValueError("Out of bounds")
100+
new_node = Node(item, current.next)
101+
current.next = new_node
102+
self.size += 1
103+
104+
def kth_element_from_end(self, position: int) -> Any:
105+
"""
106+
Find the kth node element from the end of the Linked List.
107+
This is not a zero-based index search.
108+
If position=1, it will return the last element in the list.
109+
110+
>>> linked_list = LinkedList()
111+
>>> linked_list.add(1)
112+
>>> linked_list.add(2)
113+
>>> linked_list.add(3)
114+
>>> linked_list.add(4, 2)
115+
>>> linked_list.add(5, 4)
116+
>>> print(linked_list)
117+
3 --> 2 --> 4 --> 1 --> 5
118+
>>> linked_list.kth_element_from_end(2)
119+
1
120+
>>> linked_list.kth_element_from_end(5)
121+
3
122+
>>> linked_list.kth_element_from_end(3)
123+
4
124+
>>> linked_list.kth_element_from_end(10)
125+
>>> linked_list.kth_element_from_end(0)
126+
>>> linked_list.kth_element_from_end(-5)
127+
"""
128+
if (self.head is None) or (position <= 0) or (position > self.size):
129+
return None
130+
131+
slow_pointer = fast_pointer = self.head
132+
133+
for _ in range(position):
134+
fast_pointer = fast_pointer.next
135+
136+
while fast_pointer is not None and slow_pointer is not None:
137+
slow_pointer = slow_pointer.next
138+
fast_pointer = fast_pointer.next
139+
140+
return slow_pointer.item

0 commit comments

Comments
 (0)