LeetCode 234. 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?

 


最简单的方法就是把链表变成一个数组,然后前后两个指针看对应的数字是否一样。代码写起来非常简单,时空都是O(n)。

/**
 * 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 boolean isPalindrome(ListNode head) {
        List list = new ArrayList<>();
        ListNode curr = head;
        while (curr != null) {
            list.add(curr.val);
            curr = curr.next;
        }
        int front = 0;
        int rear = list.size() - 1;
        while (front <= rear) {
            if (list.get(front) != list.get(rear)) {
                return false;
            }
            front++;
            rear--;
        }
        return true;
    }
}

还有一种递归的方法,真的好难想到且写出来……看了官方解答的动图才算是大概搞懂了它在干什么。它用了一个helper递归函数,并且用了一个全局变量front和一个递归函数里的局部变量curr记录当前需要比较哪个节点(其实有点像是先记录下从左往右的节点,再reverse linkedlist记录从右往左的节点,这两个之间做比较)。当递归curr到最深层的时候,如果是null的话直接return true了。否则的话,需要判断它的next是否满足条件,以及front和curr的val是否相等,如果同时满足的话,前后对应上了,需要移动全局的front往后,curr因为在下一次递归里自动往前了就不用管。时空都是O(n)。

可能这么写完了下次复习的时候又不记得了,贴个link在这儿看图最直观了:Official Solution - Palindrome Linked List - LeetCode

/**
 * 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 {
    private ListNode front;

    private boolean recursiveCheck(ListNode curr) {
        if (curr == null) {
            return true;
        }
        if (!recursiveCheck(curr.next) || curr.val != front.val) {
            return false;
        }
        front = front.next;
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        front = head;
        return recursiveCheck(head);
    }
}

 然后是最后一种可以达到O(1)空间的方法,是只reverse链表的后一半,相当于是206和876的合体了……solutions里也给出了一些pros and cons的比较,比如这会in place改变原先链表的结构,所以最好restore back to original,并且在concurrent环境下多线程access这个链表可能需要lock啥的。代码写起来就是206和876的两个函数,但是,需要特别注意怎么分前一半和后一半!不要盲目照搬以前的代码……就不在这里详细写了,下次复习的时候自己体会吧。这个方法还是,非常值得一写的。

/**
 * 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 boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        
        ListNode mid = getMid(head);
        ListNode reversed = reverse(mid.next);

        ListNode first = head;
        ListNode second = reversed;

        boolean result = true;  // need this because we cannot return in the while loop to restore the list
        while (result && second != null) {
            if (first.val != second.val) {
                result = false;
            }
            first = first.next;
            second = second.next;
        }
        
        // restore the reversed second half
        mid.next = reverse(reversed);

        return result;
    }

    private ListNode getMid(ListNode head) {
        // if it's odd, slow = middle
        // if it's even, slow = last one of first half
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

    private ListNode reverse(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

你可能感兴趣的:(LeetCode,leetcode)