{x}
blog image

Palindrome Linked List

Given the head of a singly linked list, return true if it is a palindrome or false otherwise.

 

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

 

Follow up: Could you do it in O(n) time and O(1) space?

Solution Explanation:

This problem asks to determine if a singly linked list is a palindrome. The most efficient solution uses a two-pointer approach and reverses the second half of the list. This allows for an O(n) time complexity solution with O(1) space complexity.

Algorithm:

  1. Find the middle: Use two pointers, slow and fast. slow moves one step at a time, while fast moves two steps at a time. When fast reaches the end, slow will be at the middle of the linked list.

  2. Reverse the second half: Reverse the linked list starting from slow.next. This is done iteratively to avoid stack overflow issues in recursive solutions.

  3. Compare: Compare the first half and the reversed second half of the list. If they are the same, the list is a palindrome; otherwise, it's not.

Time Complexity: O(n), where n is the number of nodes in the linked list. We traverse the list once to find the middle and once to reverse the second half. Comparing the two halves takes O(n/2) which is still O(n).

Space Complexity: O(1). We only use a few pointers, so the space used is constant regardless of the input size.

Code Explanation (Python as an example):

class Solution:
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        # Find the middle of the linked list
        slow, fast = head, head.next
        while fast and fast.next:
            slow, fast = slow.next, fast.next.next
 
        # Reverse the second half of the linked list
        pre, cur = None, slow.next
        while cur:
            t = cur.next
            cur.next = pre
            pre, cur = cur, t
 
        # Compare the first and reversed second halves
        while pre:
            if pre.val != head.val:
                return False
            pre, head = pre.next, head.next
        return True
 
  1. slow, fast Initialization: We initialize two pointers, slow and fast, to traverse the linked list.

  2. Finding the Middle: The while loop iterates until fast reaches the end (or one node before the end for odd length lists). This ensures slow points to the middle node.

  3. Reversing the Second Half: The next loop reverses the portion of the linked list starting from slow.next. It uses three pointers: pre (previous node), cur (current node), and t (temporary node to store the next node).

  4. Comparison: The final loop compares the values of nodes in the first half and the reversed second half. If any pair doesn't match, it returns False. Otherwise, it returns True.

The provided code in other languages follows the same logic, only differing in syntax. The core algorithm remains consistent across all implementations.