From 2bc9848d42464668f5b021d57d46a1d901b1a15d Mon Sep 17 00:00:00 2001 From: Martin Oywa Date: Tue, 7 Oct 2025 16:45:58 +0300 Subject: [PATCH 1/3] Add find kth_element_from_end in linked-lists --- .../linked_list/kth_element_from_end.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 data_structures/linked_list/kth_element_from_end.py diff --git a/data_structures/linked_list/kth_element_from_end.py b/data_structures/linked_list/kth_element_from_end.py new file mode 100644 index 000000000000..35d04670eca6 --- /dev/null +++ b/data_structures/linked_list/kth_element_from_end.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + + +@dataclass +class Node: + item: Any + next: Node | Any = None + + +class LinkedList: + def __init__(self) -> None: + self.head: Node | None = None + self.size = 0 + + def __str__(self) -> str: + if self.is_empty(): + return "" + else: + iterate = self.head + item_str = "" + item_list: list[str] = [] + while iterate: + item_list.append(str(iterate.item)) + iterate = iterate.next + + item_str = " --> ".join(item_list) + + return item_str + + def __len__(self) -> int: + return self.size + + def is_empty(self) -> bool: + return self.head is None + + def add(self, item: Any, position: int = 0) -> None: + if position < 0: + raise ValueError("Position must be non-negative") + + if position == 0 or self.head is None: + new_node = Node(item, self.head) + self.head = new_node + else: + current = self.head + for _ in range(position - 1): + current = current.next + if current is None: + raise ValueError("Out of bounds") + new_node = Node(item, current.next) + current.next = new_node + self.size += 1 + + def kth_element_from_end(self, k: int) -> Any: + """ + Find the kth node from the end of the Linked List + >>> linked_list = LinkedList() + >>> linked_list.add(1) + >>> linked_list.add(2) + >>> linked_list.add(3) + >>> linked_list.add(4, 2) + >>> linked_list.add(5, 4) + >>> print(linked_list) + 3 --> 2 --> 4 --> 1 --> 5 + >>> linked_list.kth_element_from_end(2) + 1 + >>> linked_list.kth_element_from_end(5) + 3 + >>> linked_list.kth_element_from_end(3) + 4 + >>> linked_list.kth_element_from_end(10) + >>> linked_list.kth_element_from_end(0) + >>> linked_list.kth_element_from_end(-5) + """ + if (self.head is None) or (k <= 0) or (k > self.size): + return None + + slow_pointer = fast_pointer = self.head + + for _ in range(k): + fast_pointer = fast_pointer.next + + while fast_pointer is not None and slow_pointer is not None: + slow_pointer = slow_pointer.next + fast_pointer = fast_pointer.next + + return slow_pointer.item From 60d8fa39d02901633b530ef3e294e3d509f6e18c Mon Sep 17 00:00:00 2001 From: Martin Oywa Date: Tue, 7 Oct 2025 16:55:16 +0300 Subject: [PATCH 2/3] Update kth_element_from_end docstring --- data_structures/linked_list/kth_element_from_end.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data_structures/linked_list/kth_element_from_end.py b/data_structures/linked_list/kth_element_from_end.py index 35d04670eca6..4f47e30458ff 100644 --- a/data_structures/linked_list/kth_element_from_end.py +++ b/data_structures/linked_list/kth_element_from_end.py @@ -55,7 +55,10 @@ def add(self, item: Any, position: int = 0) -> None: def kth_element_from_end(self, k: int) -> Any: """ - Find the kth node from the end of the Linked List + Find the kth node element from the end of the Linked List. + This is not a zero-based index search. + If k=1, it will return the last element in the list. + >>> linked_list = LinkedList() >>> linked_list.add(1) >>> linked_list.add(2) From f11eafa078261dd52e71310f35b58ab6c2c70553 Mon Sep 17 00:00:00 2001 From: Martin Oywa Date: Tue, 7 Oct 2025 17:07:48 +0300 Subject: [PATCH 3/3] Update kth_element_from_end k to position --- .../linked_list/kth_element_from_end.py | 84 +++++++++++++++---- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/data_structures/linked_list/kth_element_from_end.py b/data_structures/linked_list/kth_element_from_end.py index 4f47e30458ff..b994d17c4608 100644 --- a/data_structures/linked_list/kth_element_from_end.py +++ b/data_structures/linked_list/kth_element_from_end.py @@ -16,27 +16,75 @@ def __init__(self) -> None: self.size = 0 def __str__(self) -> str: - if self.is_empty(): - return "" - else: - iterate = self.head - item_str = "" - item_list: list[str] = [] - while iterate: - item_list.append(str(iterate.item)) - iterate = iterate.next + """ + >>> linked_list = LinkedList() + >>> linked_list.add(23) + >>> linked_list.add(14) + >>> linked_list.add(9) + >>> print(linked_list) + 9 --> 14 --> 23 + """ + iterate = self.head + item_str = "" + item_list: list[str] = [] + while iterate: + item_list.append(str(iterate.item)) + iterate = iterate.next - item_str = " --> ".join(item_list) + item_str = " --> ".join(item_list) - return item_str + return item_str def __len__(self) -> int: + """ + >>> linked_list = LinkedList() + >>> len(linked_list) + 0 + >>> linked_list.add("a") + >>> len(linked_list) + 1 + >>> linked_list.add("b") + >>> len(linked_list) + 2 + """ return self.size - def is_empty(self) -> bool: - return self.head is None - def add(self, item: Any, position: int = 0) -> None: + """ + Add an item to the LinkedList at the specified position. + Default position is 0 (the head). + + Args: + item (Any): The item to add to the LinkedList. + position (int, optional): The position at which to add the item. + Defaults to 0. + + Raises: + ValueError: If the position is negative or out of bounds. + + >>> linked_list = LinkedList() + >>> linked_list.add(1) + >>> linked_list.add(2) + >>> linked_list.add(3) + >>> linked_list.add(4, 2) + >>> print(linked_list) + 3 --> 2 --> 4 --> 1 + + # Test adding to a negative position + >>> linked_list.add(5, -3) + Traceback (most recent call last): + ... + ValueError: Position must be non-negative + + # Test adding to an out-of-bounds position + >>> linked_list.add(5,7) + Traceback (most recent call last): + ... + ValueError: Out of bounds + >>> linked_list.add(5, 4) + >>> print(linked_list) + 3 --> 2 --> 4 --> 1 --> 5 + """ if position < 0: raise ValueError("Position must be non-negative") @@ -53,11 +101,11 @@ def add(self, item: Any, position: int = 0) -> None: current.next = new_node self.size += 1 - def kth_element_from_end(self, k: int) -> Any: + def kth_element_from_end(self, position: int) -> Any: """ Find the kth node element from the end of the Linked List. This is not a zero-based index search. - If k=1, it will return the last element in the list. + If position=1, it will return the last element in the list. >>> linked_list = LinkedList() >>> linked_list.add(1) @@ -77,12 +125,12 @@ def kth_element_from_end(self, k: int) -> Any: >>> linked_list.kth_element_from_end(0) >>> linked_list.kth_element_from_end(-5) """ - if (self.head is None) or (k <= 0) or (k > self.size): + if (self.head is None) or (position <= 0) or (position > self.size): return None slow_pointer = fast_pointer = self.head - for _ in range(k): + for _ in range(position): fast_pointer = fast_pointer.next while fast_pointer is not None and slow_pointer is not None: