
Problem Statement
In this task, we are given the head of a singly linked list and are tasked to determine whether the sequence of values in this linked list forms a palindrome. A palindrome is a sequence that reads the same backward as forward, meaning that the first element is equal to the last, the second is equal to the second-last, and so on.
Examples
Example 1
Input:
head = [1,2,2,1]
Output:
true
Example 2
Input:
head = [1,2]
Output:
false
Constraints
- The number of nodes in the list is in the range
[1, 105]
. 0 <= Node.val <= 9
Approach and Intuition
Given the nature of singly linked lists—where each node points only to the next node—it is not trivial to traverse the list backwards. Therefore, our challenge is to verify the palindrome property without direct backward traversal.
Example 1:
- Input:
head = [1,2,2,1]
- Output:
true
Analysis:
- For a list
[1,2,2,1]
, if we read from start to end, it is1,2,2,1
, and from end to start, it’s the same. - Therefore, the list is a palindrome.
Example 2:
- Input:
head = [1,2]
- Output:
false
Analysis:
- For a list
[1,2]
, reading from start to end gives1,2
, whereas end to start gives2,1
. - Thus, the sequence is not a palindrome.
A naive approach would involve copying the linked list into an array. This changes the space complexity drastically since we are using auxiliary space proportional to the size of the linked list.
Another possible solution could involve a more space-efficient approach, such as reversing the second half of the linked list:
- Find the middle of the linked list using a slow and fast pointer approach. Fast pointer moves two steps for every step the slow pointer moves.
- Reverse the second part of the linked list.
- Compare the first part with the reversed second part; if both halves are identical, then the list is a palindrome.
Understanding these approaches and translating them into an efficient ascent matters because palindromic properties in linked list structures are not straightforward due to their linear and forward-only nature.
Solutions
- Java
- Python
class Solution {
public boolean checkPalindrome(ListNode node) {
if (node == null) return true;
// Process the first half and reverse the second half.
ListNode halfEnd = findMiddle(node);
ListNode secondPart = reverse(node.next);
// Verify palindrome condition.
ListNode firstPointer = node;
ListNode secondPointer = secondPart;
boolean isPalindrome = true;
while (isPalindrome && secondPointer != null) {
if (firstPointer.val != secondPointer.val) isPalindrome = false;
firstPointer = firstPointer.next;
secondPointer = secondPointer.next;
}
// Reconstruct the original list and return result.
halfEnd.next = reverse(secondPart);
return isPalindrome;
}
// Reverse the linked list.
private ListNode reverse(ListNode node) {
ListNode previous = null;
ListNode current = node;
while (current != null) {
ListNode nextNode = current.next;
current.next = previous;
previous = current;
current = nextNode;
}
return previous;
}
// Find the midpoint of the list (end of the first half).
private ListNode findMiddle(ListNode node) {
ListNode fast = node;
ListNode slow = node;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
The provided Java code presents a solution to check if a linked list is a palindrome. This involves confirming whether the list reads the same forwards and backwards.
- The
checkPalindrome
method begins by confirming if the linked list is empty, in which case, it immediately returnstrue
because an empty list is technically a palindrome. - It then finds the middle of the list using the
findMiddle
method and reverses the second half of the list starting from the node immediately following this midpoint. - Proceed to compare the values of the nodes from the start of the list and from the start of the reversed half. Continue this comparison until the end of the reversed list is reached or a mismatch is found.
- After checking, the second half of the list is reversed again to restore the original list structure before returning the result of the palindrome check.
The reverse
method reverses any given segment of the linked list, and the findMiddle
method locates the middle point, useful to split the list into roughly two equal parts for the comparison process.
Manage the modifications to the list carefully and ensure that the original data structure of the linked list is restored by the end of the operation. This is crucial for maintaining data integrity if the linked list is to be used after the palindrome check.
class Solution:
def checkPalindrome(self, node: ListNode) -> bool:
if node is None:
return True
half_end = self.find_half_end(node)
reverse_start = self.reverse_linked_list(half_end.next)
palindrome_check = True
first_head = node
second_head = reverse_start
while palindrome_check and second_head is not None:
if first_head.val != second_head.val:
palindrome_check = False
first_head = first_head.next
second_head = second_head.next
half_end.next = self.reverse_linked_list(reverse_start)
return palindrome_check
def find_half_end(self, node: ListNode) -> ListNode:
rapid = node
slow = node
while rapid.next is not None and rapid.next.next is not None:
rapid = rapid.next.next
slow = slow.next
return slow
def reverse_linked_list(self, node: ListNode) -> ListNode:
prev = None
curr = node
while curr is not None:
next_temp = curr.next
curr.next = prev
prev = curr
curr = next_temp
return prev
This Python implementation checks if a singly linked list is a palindrome. The algorithm involves identifying the middle of the list, reversing the second half, and then comparing it with the first half for equality. Follow the steps outlined in the provided code:
Define the method
checkPalindrome
which checks if the linked list starting from the givennode
is a palindrome.- Immediately return
True
if the input node isNone
. An empty list is considered a palindrome. - Find the end node of the first half of the list using the
find_half_end
method. - Reverse the second half of the list starting from the node next to the found end node using the
reverse_linked_list
method.
- Immediately return
Iterate simultaneously through the nodes of the first half and the reversed second half.
- A mismatch between values of corresponding nodes in these two halves indicates the list isn't a palindrome.
Restore the list to its original structure by reversing the second half back and linking it to the first half.
The
find_half_end
method locates the end of the first half using the slow and rapid (fast) pointer technique. Slow pointer moves one step at a time, while rapid pointer moves two steps.reverse_linked_list
reverts the part of the list passed to it by adjusting pointers of each node.
By using these methods, the space complexity is minimized, effectively using just O(1) additional space aside from the input list. The time complexity is O(n), where n is the number of nodes in the list, since each node is visited a constant number of times. This solution ensures that the structure of the original linked list is maintained after the palindrome check.
No comments yet.