[LeetCode题解]234. 回文链表 | 快慢指针 + 反转链表

解题思路

找到后半部分链表,再反转。然后与前半部分链表比较

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public bool IsPalindrome(ListNode head) {
        if(head == null || head.next == null) {
            return true;
        }

        // 思路:找到后半部分链表,再反转。然后与前半部分链表比较
        
        // 找到后半部分且反转
        ListNode firstHalfEnd = EndOfFirstHalf(head);
        ListNode secondHalfStart = Reverse(firstHalfEnd.next);

        bool result = true;
        ListNode p = head, q = secondHalfStart;
        while(result && q != null) {    // 前半部分链表与反转后的后半部分链表逐一比较
            if(p.val != q.val) {
                result = false;
            }
            p = p.next;
            q = q.next;
        }

        firstHalfEnd.next = Reverse(secondHalfStart);       // 还原链表

        return result;
    }

    // 使用快慢指针来找到前半部分链表的尾节点
    private ListNode EndOfFirstHalf(ListNode head) {
        ListNode fast = head, 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 cur = head, pre = null;
        while(cur != null) {
            var nextTmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nextTmp; 
        }

        return pre;
    }
}

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 为链表的长度。只使用了三次遍历,去掉常数后,仍为 \(O(n)\)
  • 空间复杂度:\(O(1)\)。只使用了常数个变量保存节点指针。
posted @ 2020-11-20 22:18  大杂草  阅读(192)  评论(0编辑  收藏  举报