Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Problem1_BinarySearchTreeIterator.py
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions Problem2_ReorderList.py
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions Problem3_DeleteWithoutHeadPointer.py
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions Problem4_IntersectionOfTwoLinkedLists.py
Original file line number Diff line number Diff line change
@@ -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