2095. Delete the Middle Node of a Linked List
Problem Solving - Day 14
Hello, reader ๐๐ฝ ! Welcome to day 14 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.
Today, I will be picking up LeetCode's daily challenge problem: 2095. Delete the Middle Node of a Linked List.
๐ค Problem Statement
- Given the head of a linked list, delete the node in the middle of the list and return the head of the updated list.
Note: the middle of a list with n nodes is at position floor(n/2).
- E.g.:
Input: head = [1,3,4,7,1,2,6] => Output: [1,3,4,1,2,6]
.Input: head = [1,2] => Output: [1]
.Input: head = [1,3,4] => Output: [1,4]
.
๐ฌ Initial Thoughts
- Since we need to remove the node in the middle of the list given the head, we need access to the node previous to the middle node.
- Hence, this question can be split into 2 ways:
- Get the node previous to the middle of the list
- Update the pointers to remove the middle node.
- There are 2 methods to solve this problem:
- 2 Passes
- 2 Pointers
๐ฌ Thought Process - 2 Passes
- The first way to access the previous node is to traverse until the count of nodes is less than n/2.
- But to get the [n/2]th node, we need the value of n (number of nodes/ length of the list).
The simplest way to get the length is to keep track of a count variable and traverse till the end of the list.
Once we have access to the previous node, all we have to do is update the next pointer of the previous node:
- Let's look at the code for this solution.
๐ฉ๐ฝโ๐ป Solution - 2 Passes
Below is the code for the above 2 passes approach
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode deleteMiddle(ListNode head) { if(head == null || head.next == null) { return null; } int length = getLength(head); ListNode prevToMiddleNode = getPreviousToMiddleNode(head, length); prevToMiddleNode.next = prevToMiddleNode.next.next; return head; } private int getLength(ListNode head) { int length = 0; ListNode ptr = head; while(ptr != null) { length++; ptr = ptr.next; } return length; } private ListNode getPreviousToMiddleNode(ListNode head, int n) { int middle = n/2; ListNode ptr = head; int count = 0; while(count < middle-1) { ptr = ptr.next; count++; } return ptr; } }
Time Complexity: O(n) - Since we are traversing all the nodes to get the length of the list. Space Complexity: O(1) - Since we only use temporary node to traverse the list.
๐ฌ Thought Process - 2 Pointers
- Another way to get the middle of the list is using two pointers technique.
- We maintain two pointers: slow and fast such that at every iteration, slow moves forward by one node, and fast moves two nodes ahead.
- The slow pointer ultimately reaches the middle by the time either the fast is null (when list length is even) or the fast pointer is at the last node (when list length is odd).
Refer to the image below to see how this works when the number of nodes is odd:
Refer to the image below to see how this works when the number of nodes is even:
- To get the node previous to the middle, we start the slow pointer with null instead of head, i.e., one node slower than how the slow pointer was before.
- This way when the fast pointer reaches null or the last node, the slow stops at the node previous to middle.
Refer to the image below to see how the slow pointer begins from null.
Now we can easily update the pointer of the previous node as shown below.
๐ฉ๐ฝโ๐ป Solution - 2 Passes
Below is the code for the 2 pointers approach to delete the middle node:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode deleteMiddle(ListNode head) { if(head == null || head.next == null) { return null; } ListNode prevToMiddleNode = getPreviousNodeToMiddle(head); prevToMiddleNode.next = prevToMiddleNode.next.next; return head; } private ListNode getPreviousNodeToMiddle(ListNode head) { ListNode prev = null, fast = head; while(fast != null && fast.next != null) { prev = (prev == null) ? head : prev.next; fast = fast.next.next; } return prev; } }
Time Complexity: O(n) - Since we are traversing all the nodes to reach the previous node before the middle. Space Complexity: O(1) - Since we only use temporary nodes to traverse the list.
You can find the code for this problem on GitHub repo: 2095. Delete the Middle Node of a Linked List.
Conclusion
That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!
Thank you for reading!