LeetCode 234. Palindrome Linked List 回文链表(Java)

题目:

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

Example 1:
Input: 1->2
Output: false

Example 2:
Input: 1->2->2->1
Output: true

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

解答:

判断一个链表是否为回文链表,直观想到的是将链表的前后部分对应位置分别进行比对。则应该先将链表分为前后两部分。因为链表只能直接找到节点的后继,而不能直接找到节点的前驱,所以将划分出来的后半段链表进行逆置反转,再将前后两段链表从头到尾进行比对。

具体思路如下:

  1. 判空
  2. 寻找链表的中间节点。
    • 采用快慢指针的方式。(在之前的解题中学习过,快慢指针经常被应用于链表中寻找某一节点。)
    • 若链表节点为奇数,则当fast==null时,慢指针指向中间节点 middle。则将 middle.next 作为后半段链表的头结点进行反转。
    • 若链表节点为偶数,则当fast.next==null时,慢指针指向中间两个节点的第一个节点,即 middle 指向前半段节点的尾节点,则将 middle.next 作为后半段链表的头结点进行反转
  3. 将中间节点下一跳 middle.next 作为头节点,进行反转,采用递归的方式
  4. 将前后两段节点进行逐个比对,前半段节点从 head 开始,后半段节点从反转后的头结点 newhead 开始
  5. 若对应节点不相同,则return false,若相同则 l1 和 l2 后移一位
class Solution {
    public boolean isPalindrome (ListNode head) {
        if(head==null || head.next==null) {
            return true;
        }
        ListNode middle = findMiddle(head);
        ListNode l1 = head;
        ListNode l2 = reverse(middle.next);
        while(l1!=null && l2!=null) {
            if(l1.val!=l2.val){
                return false;
            }else{
                l1=l1.next;
                l2=l2.next;
            }            
        }
        return true;
    }
    
    //寻找链表中间节点
    private ListNode findMiddle (ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast!=null && fast.next!=null) {
            slow=slow.next;
            fast=fast.next.next;
        }
        return slow;
    }
    
    //反转中间节点后半段链表
    private ListNode reverse (ListNode head) {
        if(head==null || head.next==null) {
            return head;
        }
        ListNode newhead = reverse(head.next);
        head.next.next=head;
        head.next=null;
        return newhead;
    }
}

关于快慢指针,参考LeetCode 141,链接:Linked List Cycle 环形链表
关于反转链表,参考LeetCode 206,链接:Reverse Linked List 反转链表

你可能感兴趣的:(LeetCode)