The middle element is ignored during the comparison since it does not affect the palindrome property.
Key takeaways:
The two pointer technique checks if a linked list is a palindrome by utilizing the properties of the list's structure without extra space for reversal.
Reversing the second half of the list in place helps compare it against the first half to determine if the list reads the same forward and backward.
Two pointers approach ensures that the comparison only requires one traversal of each half, maintaining an optimal
time complexity. The space complexity is
as the algorithm modifies the list in place, unlike approaches that require extra storage.
A palindrome is a sequence that reads the same forwards as it does backward. For instance, the number
The challenge is to determine whether a singly linked list is a palindrome. Given the head of the linked list, the goal is to implement an algorithm to check if it is a palindrome or not.
Constraints:
nodes
nodes.data
Let’s take a look at a few examples to get a better understanding of the problem statement:
Let’s take a moment to make sure you’ve correctly understood the problem. The quiz below helps you check if you’re solving the correct problem:
Checking if a linked list is a palindrome
(True or False) Is the given linked list a palindrome?
True
False
The challenge of checking if a linked list is a palindrome arises from its one-way traversal nature. Unlike arrays or strings, linked lists cannot be directly reversed or indexed. However, we can leverage the two-pointer technique to split the list into two halves. By reversing the second half in place, we can compare the two halves without requiring additional space, ensuring an optimal solution. After comparison, the original structure can be restored, making this approach efficient and non-destructive.
Here’s how the algorithm works:
Use the two-pointer technique (fast and slow pointers) to identify the midpoint of the linked list.
The slow pointer moves one step at a time.
The fast pointer moves two steps at a time.
By the time the fast pointer reaches the end, the slow pointer will be in the middle.
Reverse the second half of the linked list starting from the slow pointer.
Traverse the first half (starting from the head) and the reversed second half. Compare the values at each corresponding position.
Reverse the second half again to restore the linked list to its original order (if needed).
If all values match during the comparison, the list is a palindrome; otherwise, it is not.
Let’s look at the following illustration to get a better understanding of the solution:
Let’s look at the Python code for the algorithm we just discussed:
# Class definition for a singly linked list nodeclass ListNode:def __init__(self, data=0, next=None):self.data = dataself.next = next# Function to create a linked list from a list of valuesdef create_linked_list(values):if not values:return Nonehead = ListNode(values[0])current = headfor data in values[1:]:current.next = ListNode(data)current = current.nextreturn head# Function to print the linked listdef print_linked_list(head):result = []while head:result.append(head.data)head = head.nextreturn " -> ".join(map(str, result))# Function to check if a linked list is a palindromedef is_palindrome(head):# Step 1: Use two pointers (slow and fast) to find the middle of the listslow, fast = head, headwhile fast and fast.next:slow = slow.next # Move slow pointer by 1 stepfast = fast.next.next # Move fast pointer by 2 steps# Step 2: Reverse the second half of the listprev = Nonewhile slow:temp = slow.nextslow.next = prevprev = slowslow = temp# Step 3: Compare the first half with the reversed second halfleft, right = head, prevwhile right:# Mismatch foundif left.data != right.data:return Falseleft = left.next # Move to the next node in the first halfright = right.next # Move to the next node in the reversed second half# The linked list is a palindromereturn True# Driver codedef main():lists = [[4, 7, 4, 1, 2, 3, 2, 1, 4, 7, 4],[1, 2, 2, 1],[1, 2, 3],[1, 4, 7, 2, 1],[1]]for i, list in enumerate(lists, 1):head = create_linked_list(list)print(i, ".\tLinked List:", print_linked_list(head))print(f"\n\tIs Palindrome? {'Yes' if is_palindrome(head) else 'No'}")print("-" * 100)if __name__ == "__main__":main()
If you’re eager to learn problem-solving strategies, "Grokking the Coding Interview Patterns" explores 26 essential patterns, including the Two Pointers pattern, and applies them to various real-world coding problems.
The time complexity of the is_palindrome
function is
The space complexity of the function is
If you further want to explore the two pointers pattern and the problems it solves, here are some of the problems solved by the two pointers pattern:
Haven’t found what you were looking for? Contact Us
Free Resources