Part1
Reverse a Linked List
❓: Given the head of a singly linked list, write a program to reverse the linked list, and return the head pointer to the reversed list.
# iterative approach
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
curr = head
while curr:
next_pointer = curr.next
curr.next = prev
prev = curr
curr = next_pointer
return prev
Middle of a Linked List
❓: Given the head of a linked list of integers, determine the middle node of the linked list. However, if the linked list has an even number of nodes, return the second middle node.
🧠:
1. Use slow and fast pointers where fast pointer moves 2 steps and slow pointers moves 1 step at a time
2. When fast pointer is at the end of linked list, slow pointer will be in the middle
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
if fast.next is None:
return slow
if fast.next.next is None:
return slow.next
Remove nth node from end
❓: Given a linked list and an integer N, the task is to delete the Nth node from the end of the linked list and print the updated linked list.
🧠:
1. Use 2 pointers slow and fast. Move fast pointer first from head by n steps
2. Now move the slow pointer till fast pointer reaches end.
3. Now the slow pointer's next node needs to be removed
4. Handle the edge case in the start if fast pointer moves beyond linked list
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
fast = head
for _ in range(n):
fast = fast.next
if fast is None:
return head.next
slow = head
while fast and fast.next:
slow = slow.next
fast = fast.next
slow.next = slow.next.next
return head
Add 2 Numbers
❓: Given the heads of two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
🧠:
1. Iterate through both linked lists by carrying current remainder
2. Create new node with the remainder and curr sum and return the final linked list
class Solution:
def addTwoNumbers(
self, l1: Optional[ListNode], l2: Optional[ListNode]
) -> Optional[ListNode]:
res = curr = None
remainder = curr_sum = 0
while l1 or l2:
curr_sum = (l1.val if l1 else 0) + (l2.val if l2 else 0) + remainder
remainder = curr_sum // 10
new_node = ListNode(val=curr_sum % 10)
if curr is None:
res = new_node
curr = new_node
else:
curr.next = new_node
curr = curr.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
if remainder:
curr.next = ListNode(val=remainder)
return res
Delete the given node
❓: Write a function to delete a node in a singly-linked list. You will not be given access to the head of the list instead, you will be given access to the node to be deleted directly. It is guaranteed that the node to be deleted is not a tail node in the list.
🧠:
Replace the node value with next node value and make next node as next node's next
class Solution:
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val = node.next.val
node.next = node.next.next