delete the middle node of a linked list
intuition
Base Case Check:
- If head is null, the list is empty. The method returns null since there’s nothing to delete.
**Initialization: **
- A dummy node, prev, is created and its next pointer is set to head. This dummy node serves as a placeholder to simplify edge case handling, especially when the list has only one node or when we need to delete the first real node of the list.
- Two pointers, slow and fast, are initialized: slow starts at prev and fast starts at head.
Traversal:
- The list is traversed using the two-pointer technique where fast moves twice as fast as slow. For every move fast makes two steps (if possible), slow makes one step.
- This traversal continues until fast reaches the end of the list (fast is null) or fast is at the last node (fast.next is null). At this point, slow will be just before the middle node of the list. This is because while fast moves through the entire list, slow moves only half the distance.
Deletion:
- Once the traversal is complete, slow is either at the node just before the middle of the list (for odd-length lists) or at the node before the second middle node (for even-length lists, where there are two middle nodes, and the first one is considered the middle for deletion).
- The middle node is then removed by adjusting the next pointer of the slow node to skip over the middle node and point directly to the node after the middle node. This effectively removes the middle node from the list.
Return:
- Finally, the method returns the new list, but since the prev node was a dummy node added at the start, the method returns prev.next to return the actual head of the modified list.
delete the middle node of a linked list
code
def deleteMiddle(head):
"""
:type head: Optional[ListNode]
:rtype: Optional[ListNode]
"""
if head == None :return None
prev = ListNode(0)
prev.next = head
slow = prev
fast = head
while fast != None and fast.next != None:
slow = slow.next
fast = fast.next.next
slow.next = slow.next.next
return prev.nextodd even linked list
intuition
Base Case Handling: The code first checks if the input list is either empty (head == null) or contains only one node (head.next == null). In either case, the list doesn’t need rearranging, so the original head of the list is returned immediately.
Dummy Head Initialization: Two dummy head nodes, odd and even, are created. These nodes serve as the starting points for two separate lists: one to collect all nodes from odd positions and the other for nodes from even positions. This is a common technique used to simplify list manipulation by avoiding dealing with special cases for the head node.
**Pointer Initialization: **Two pointers, odd_ptr and even_ptr, are initialized to point to the respective dummy heads. These pointers will traverse the lists, allowing new nodes to be appended to the respective odd and even lists.
List Traversal and Node Classification: The code enters a loop that continues until all nodes from the original list (head) have been processed. Within the loop, an index variable is used to determine whether the current node is at an odd or even position:
Linking Odd and Even Lists: After all nodes have been classified and the original list has been fully traversed, the code performs two crucial steps to finalize the rearrangement:
Returning the Result: Finally, the method returns odd.next, which points to the first real node in the odd list, effectively skipping the odd dummy head. This is the new head of the rearranged list where all odd-positioned nodes are followed by all even-positioned nodes.
odd even linked list
code
Definition for singly-linked list.
# class ListNode(object):
# def \_\_init\_\_(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def oddEvenList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None : return head
odd = ListNode(0)
odd_ptr = odd
even = ListNode(0)
even_ptr = even
idx = 1
while head != None :
if idx % 2 == 0:
even_ptr.next = head
even_ptr = even_ptr.next
else:
odd_ptr.next = head
odd_ptr = odd_ptr.next
head = head.next
idx+=1
even_ptr.next = None
odd_ptr.next = even.next
return odd.nextreverse linked list
intuition
Assume that we have linked list 1 → 2 → 3 → Ø, we would like to change it to Ø ← 1 ← 2 ← 3.
While traversing the list, we can change the current node’s next pointer to point to its previous element. Since a node does not have reference to its previous node, we must store its previous element beforehand. We also need another pointer to store the next node before changing the reference. Do not forget to return the new head reference at the end!
reverse linked list
code
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
prev = None
curr = head
while curr:
next_temp = curr.next
curr.next = prev
prev = curr
curr = next_temp
return prevmaximum twin sum of a linked list
intuition
maximum twin sum of a linked list
code
class Solution(object):
def pairSum(self, head):
current = head
st = []
maximumSum = 0
while current:
st.append(current.val)
current = current.next
current = head
size = len(st)
count = 1
maximumSum = 0
while count <= size/2:
maximumSum = max(maximumSum, current.val + st.pop())
current = current.next
count = count + 1
return maximumSum