From fb7d040c7ac4bfb28a469ca5e81f73171b12cf15 Mon Sep 17 00:00:00 2001 From: Neeraj Date: Wed, 21 Jan 2026 19:47:32 -0800 Subject: [PATCH] Solutions for all Linked-List-2 problems --- Problem1_BinarySearchTreeIterator.py | 37 +++++++++++++++++ Problem2_ReorderList.py | 51 ++++++++++++++++++++++++ Problem3_DeleteWithoutHeadPointer.py | 24 +++++++++++ Problem4_IntersectionOfTwoLinkedLists.py | 32 +++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 Problem1_BinarySearchTreeIterator.py create mode 100644 Problem2_ReorderList.py create mode 100644 Problem3_DeleteWithoutHeadPointer.py create mode 100644 Problem4_IntersectionOfTwoLinkedLists.py diff --git a/Problem1_BinarySearchTreeIterator.py b/Problem1_BinarySearchTreeIterator.py new file mode 100644 index 00000000..da7881a0 --- /dev/null +++ b/Problem1_BinarySearchTreeIterator.py @@ -0,0 +1,37 @@ +# Time Complexity : O(1) amortized for next() and hasNext(), O(h) for initialization where h is height +# Space Complexity : O(h) for the stack +# Did this code successfully run on Leetcode : Yes +# Any problem you faced while coding this : No + +# Approach: Use a stack to store nodes for controlled inorder traversal. +# Initialize by pushing all left nodes from root. For next(), pop from stack, push all left nodes of right child. +# hasNext() checks if stack is non-empty. + +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +class BSTIterator: + def __init__(self, root: Optional[TreeNode]): + self.stack = [] + # Push all left nodes from root + self._push_all_left(root) + + def _push_all_left(self, node): + while node: + self.stack.append(node) + node = node.left + + def next(self) -> int: + # Pop the smallest element + node = self.stack.pop() + # Push all left nodes of the right child + if node.right: + self._push_all_left(node.right) + return node.val + + def hasNext(self) -> bool: + return len(self.stack) > 0 diff --git a/Problem2_ReorderList.py b/Problem2_ReorderList.py new file mode 100644 index 00000000..5fafda16 --- /dev/null +++ b/Problem2_ReorderList.py @@ -0,0 +1,51 @@ +# Time Complexity : O(n) where n is the number of nodes +# Space Complexity : O(1) +# Did this code successfully run on Leetcode : Yes +# Any problem you faced while coding this : No + +# Approach: Split list into two halves, reverse the second half, then merge them alternately. +# Use slow and fast pointers to find middle, reverse second half, then interleave nodes from both halves. + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next + +class Solution: + def reorderList(self, head: Optional[ListNode]) -> None: + """ + Do not return anything, modify head in-place instead. + """ + if not head or not head.next: + return + + # Step 1: Find the middle of the list + slow = fast = head + while fast.next and fast.next.next: + slow = slow.next + fast = fast.next.next + + # Step 2: Split into two lists and reverse the second half + second = slow.next + slow.next = None # Break the connection + + # Reverse the second half + prev = None + current = second + while current: + next_node = current.next + current.next = prev + prev = current + current = next_node + second = prev + + # Step 3: Merge the two lists alternately + first = head + while second: + temp1 = first.next + temp2 = second.next + first.next = second + second.next = temp1 + first = temp1 + second = temp2 diff --git a/Problem3_DeleteWithoutHeadPointer.py b/Problem3_DeleteWithoutHeadPointer.py new file mode 100644 index 00000000..0b20a8cc --- /dev/null +++ b/Problem3_DeleteWithoutHeadPointer.py @@ -0,0 +1,24 @@ +# Time Complexity : O(1) +# Space Complexity : O(1) +# Did this code successfully run on Leetcode : Yes +# Any problem you faced while coding this : No + +# Approach: Copy the value of next node to current node, then delete the next node. +# Since we can't access the previous node, we simulate deletion by copying next node's data and removing next node. + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def deleteNode(self, node): + """ + :type node: ListNode + :rtype: void Do not return anything, modify node in-place instead. + """ + # Copy the value from next node + node.val = node.next.val + # Delete the next node by pointing to next.next + node.next = node.next.next diff --git a/Problem4_IntersectionOfTwoLinkedLists.py b/Problem4_IntersectionOfTwoLinkedLists.py new file mode 100644 index 00000000..6759a378 --- /dev/null +++ b/Problem4_IntersectionOfTwoLinkedLists.py @@ -0,0 +1,32 @@ +# Time Complexity : O(m + n) where m and n are lengths of the two lists +# Space Complexity : O(1) +# Did this code successfully run on Leetcode : Yes +# Any problem you faced while coding this : No + +# Approach: Use two pointers starting from headA and headB, switching to the other list when reaching end. +# If lists intersect, pointers will meet at intersection point after traversing (m + n) nodes total. +# If no intersection, both pointers will be None simultaneously. + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]: + if not headA or not headB: + return None + + pointerA = headA + pointerB = headB + + # Traverse both lists, switching to the other when reaching end + # This ensures both pointers traverse the same total distance + while pointerA != pointerB: + # Move to next node, or switch to other list if at end + pointerA = pointerA.next if pointerA else headB + pointerB = pointerB.next if pointerB else headA + + # Either both are None (no intersection) or both point to intersection + return pointerA