Description:
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
Link:
https://leetcode.com/problems/palindrome-linked-list/#/description
解题方法:
难点在于如果在O(n) time and O(1) space解决这个问题。
可以用找链表中位数+反转后一半链表的方法处理链表,然后对比左半段链表和右半段链表。
找中位数用快慢指针非常简单,因为实际上是找到右半段链表前面一个结点,所以都不需要考虑奇偶问题,当快指针触底直接返回慢指针就可以。
不用额外空间反转链表(递归):
输入参数:右边结点的第一个作为curr
,和这个结点的前一个结点作为prev
。
函数出口:当curr->next == NULL
时,直接修改curr
的next
为记录的前一个节点,返回这个节点也就是反转后的head
。
函数体:用一个next
记录curr->next
,然后使curr->next = prev
;完成一次反转,将next
作为下一次的curr
,现在的curr
作为下一次的prev
。
Tips:
在反转链表时,不要把prev
初始化为中位数的那个结点,这样最后比较的时候会进入死循环,应该把prev
初始化为NULL
。
Time Complexity:
时间:O(N)
空间:O(1)
完整代码:
bool isPalindrome(ListNode* head)
{
if(head == NULL || head->next == NULL)
return true;
ListNode* median = findMedian(head);
ListNode* rList = reverseList(NULL, median->next);
ListNode* lList = head;
while(rList != NULL)
{
if(rList->val != lList->val)
return false;
rList = rList->next;
lList = lList->next;
}
return true;
}
ListNode* reverseList(ListNode* prev, ListNode* curr)
{
if(curr->next == NULL)
{
curr->next = prev;
return curr;
}
ListNode* N = curr->next;
curr->next = prev;
return reverseList(curr, N);
}
ListNode* findMedian(ListNode* head)
{
ListNode* slow = head;
ListNode* fast = head;
while(fast != NULL)
{
if(fast->next == NULL || fast->next->next == NULL)
return slow;
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
网友评论