PU Palindrome Linked List

Jan 01, 1970

Given a singly linked list, determine if it is a palindrome.

  • Could you do it in O(n) time and O(1) space?

C Solution 1:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *reverse(struct ListNode *head) {
    struct ListNode *n = 0;
    while (head) {
        struct ListNode *tmp = head->next;
        head->next = n;
        n = head;
        head = tmp;
    }
    return n;
}
bool isPalindrome(struct ListNode* head) {
    if (!head || !head->next) return true;
    struct ListNode *slow = head;
    struct ListNode *fast = head->next;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }
    slow = reverse(slow->next);
    while (slow && slow->val == head->val) {
        slow = slow->next;
        head = head->next;
    }
    return !slow;
}

C Solution 2:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool isPalindrome(struct ListNode* head) {
    struct ListNode *slow = head, *fast = head;
    head = 0;
    while (fast && fast->next) {
        fast = fast->next->next;
        struct ListNode *p = slow->next;
        slow->next = head;
        head = slow;
        slow = p;
    }
    if (fast) slow = slow->next;
    while (slow && slow->val == head->val) {
        slow = slow->next;
        head = head->next;
    }
    return !slow;
}

Python Solution 1:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        def reverse(head):
            tail, head = head, None
            while tail:
                head, tail.next, tail = tail, head, tail.next
            return head

        if not head or not head.next: return True
        slow, fast = head, head.next
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        right = reverse(slow.next)
        while right and right.val == head.val:
            right = right.next
            head = head.next
        return not right

Python Solution 2:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if not head or not head.next: return True
        slow = fast = head
        left = None
        while fast and fast.next:
            fast = fast.next.next
            left, slow.next, slow = slow, left, slow.next
        if fast: slow = slow.next
        while left and left.val == slow.val:
            left = left.next
            slow = slow.next
        return not left

Summary:

  1. 12ms, 71.87%
  2. reverse the left side during finding the middle node, compare.
  3. Sometimes, don't consider the corner case too much in the beginning. Consider it later.
  4. Python solution 2 is so beautiful.

LeetCode: 234. Palindrome Linked List