Palindrome Linked List
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?
提示 |
解題應用 |
LinkedList |
Pointer |
Default:
1 2 3 4 5 6 7 8 9 10
| func isPalindrome(head *ListNode) bool { }
|
解答思路:
在寫之前會發現到Follow up希望你能達到的條件,不過我認為要嚴格達到是非常具有爭議性的,因為要做回文的判斷,偏偏此題LinkedList的節點又是不可逆,此外用字串來強制儲存正反兩面做比較(可以參考:Valid Palindrome),畢竟存的值不是字串會有正負數上處理的麻煩及負號會導致不對稱,所以最後的結論就是先找到中間節間為開始倒著回去的部分,接著就是將原本中間到最後的部分反轉,便同時與前面的部分開始遍歷比較是否相同,而爭議點在於反轉所花費的空間與時間,總之就先以此方式來當作目前最佳的解決方案。
程式碼解說:
一開始先判斷LinkedList是否為nil,接著就是要來找出中間節點的位置,同時兩個指標以1:2的速度來遍歷整個LinkedList,當速度比較快的指標到底時,此時比較慢的指標會位在前半部最後一個節點的位置上,正如先前所說,這時就可以將後半部的部分給反轉,而在那之前要先將比較慢的指標位置往後移一格,變成後半LinkedList的開頭,最後與前半部開始同時遍歷一一檢查值是否相同,直到後半部的節點到達底部都沒有問題才回傳true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| func isPalindrome(head *ListNode) bool { if head == nil { return true } fast := head.Next slow := head for fast != nil && fast.Next != nil { fast = fast.Next.Next slow = slow.Next } slow = reverse(slow.Next) for slow != nil { if head.Val != slow.Val { return false } head = head.Next slow = slow.Next } return true }
|
先前就有題目需要反轉LinkedList,此時就可以派上用場,詳細的解說可以參考:Reverse Linked List
1 2 3 4 5 6 7 8 9 10 11
| func reverse(head *ListNode) *ListNode { var preNode *ListNode var tmp *ListNode for head != nil { tmp = head head = head.Next tmp.Next = preNode preNode = tmp } return tmp }
|
完整程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| func isPalindrome(head *ListNode) bool { if head == nil { return true } fast := head.Next slow := head for fast != nil && fast.Next != nil { fast = fast.Next.Next slow = slow.Next } slow = reverse(slow.Next) for slow != nil { if head.Val != slow.Val { return false } head = head.Next slow = slow.Next } return true } func reverse(head *ListNode) *ListNode { var preNode *ListNode var tmp *ListNode for head != nil { tmp = head head = head.Next tmp.Next = preNode preNode = tmp } return tmp }
|
總結:
若要檢查一單向LinkedList是否為回文,且其節點所儲存的值非為字串,此時可以先找出中間節點的位置,接著將後半的LinkedList做反轉,最後再同時與前面的部分開始遍歷比較是否相同。