解题思路
找到后半部分链表,再反转。然后与前半部分链表比较
代码
/**
* 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))。只使用了常数个变量保存节点指针。