Leetcode 234. Palindrome Linked List

GoodJobJasper發表於2020-12-27

在這裡插入圖片描述
方法1: 先reverse linked list,然後再與原先的list比較是否相同。這邊需要注意一點,reverse操作會改變原先的list,這個無法避免。所以我們需要事先用一個arraylist存放原來list各個node的值。時間複雜n,空間複雜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 myList = new ArrayList();
        // reverse
        ListNode prev = null;
        ListNode curr = head;
        while(curr != null){
            myList.add(curr.val);
            ListNode temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }
        
        for(int i = 0; i < myList.size(); ++i){
            if(!myList.get(i).equals(prev.val)){
                return false;
            }
            prev = prev.next;
        }
        return true;
    }
}

方法2: recursion。我自己也寫了自己的resursion,但是非常的慢,差一點tle。但是我的reursion非常的直白,比較好理解。lc給出的recursion方法非常好,但是我覺得比較難想到。兩種recursion時間空間複雜度均是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) {
        if(head == null || head.next == null ){
            return true;
        }
        
        ListNode curr = head;
        while(curr.next.next!= null){
            curr = curr.next;
        }
        if(curr.next.val != head.val){
            return false;
        }
        curr.next = null;
        return isPalindrome(head.next);
    }
}
// lc的
class Solution {

    private ListNode frontPointer;

    private boolean recursivelyCheck(ListNode currentNode) {
        if (currentNode != null) {
            if (!recursivelyCheck(currentNode.next)) return false;
            if (currentNode.val != frontPointer.val) return false;
            frontPointer = frontPointer.next;
        }
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
}

方法3: reverse second half of linked list。然後比較前後兩個list是否相等,相等返回true。這個方法巧妙的避開了使用多餘的資料結構來儲存原先的list,因為他相當於把原先的list一分為二了。時間複雜度n,空間複雜度1.

/**
 * 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) {
        // find the middle point
        ListNode fast = head, slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        
        // reverse second half
        ListNode curr = slow;
        ListNode prev = null;
        while(curr != null){
            ListNode temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }
        
        // check if is palindrome
        if(fast == null){
            // even
            while(prev != null){
                if(prev.val != head.val) return false;
                prev = prev.next;
                head = head.next;
            }
        }else{
            // odd
            while(prev.next != null){
                if(prev.val != head.val) return false;
                prev = prev.next;
                head = head.next;
            }
        }
        return true;
    }
}

總結:

  • 非常好的題目,很經典
  • reverse llinkedlist避免不了修改原list
  • 找linkedlist中點可以用two pointer方法,龜兔賽跑

相關文章