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
解題方法:
難點(diǎn)在于如果在O(n) time and O(1) space解決這個(gè)問(wèn)題。
可以用找鏈表中位數(shù)+反轉(zhuǎn)后一半鏈表的方法處理鏈表,然后對(duì)比左半段鏈表和右半段鏈表。
找中位數(shù)用快慢指針?lè)浅:?jiǎn)單,因?yàn)閷?shí)際上是找到右半段鏈表前面一個(gè)結(jié)點(diǎn),所以都不需要考慮奇偶問(wèn)題,當(dāng)快指針觸底直接返回慢指針就可以。
不用額外空間反轉(zhuǎn)鏈表(遞歸):
輸入?yún)?shù):右邊結(jié)點(diǎn)的第一個(gè)作為curr
,和這個(gè)結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)作為prev
。
函數(shù)出口:當(dāng)curr->next == NULL
時(shí),直接修改curr
的next
為記錄的前一個(gè)節(jié)點(diǎn),返回這個(gè)節(jié)點(diǎn)也就是反轉(zhuǎn)后的head
。
函數(shù)體:用一個(gè)next
記錄curr->next
,然后使curr->next = prev
;完成一次反轉(zhuǎn),將next
作為下一次的curr
,現(xiàn)在的curr
作為下一次的prev
。
Tips:
在反轉(zhuǎn)鏈表時(shí),不要把prev
初始化為中位數(shù)的那個(gè)結(jié)點(diǎn),這樣最后比較的時(shí)候會(huì)進(jìn)入死循環(huán),應(yīng)該把prev
初始化為NULL
。
Time Complexity:
時(shí)間: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;
}