LeetCode234.迴文連結串列
阿新 • • 發佈:2021-09-06
題目
給你一個單鏈表的頭節點 head ,請你判斷該連結串列是否為迴文連結串列。如果是,返回 true ;否則,返回 false 。
示例 1:
輸入:head = [1,2,2,1]
輸出:true
示例 2:
輸入:head = [1,2]
輸出:false
提示:
連結串列中節點數目在範圍[1, 105] 內
0 <= Node.val <= 9
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/palindrome-linked-list
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
解題方法
將值複製到陣列中後用雙指標
1.複製連結串列的值到陣列中
2.使用雙指標判斷是否為迴文
時間複雜度:O(n)空間複雜度:O(n)
遞迴
時間複雜度:O(n)空間複雜度:O(n)
快慢指標
1.找到前半部分連結串列的位節點
2.反轉後半部分連結串列
3.判斷是否迴文
4.恢復連結串列
5.返回結果
時間複雜度:O(n)空間複雜度:O(1)
程式碼
type ListNode struct { Val int Next *ListNode } // 陣列+雙指標 func isPalindrome(head *ListNode) bool { vals := []int{} // 遍歷一遍節點值新增到陣列 for ;head != nil;head = head.Next{ vals = append(vals,head.Val) } n := len(vals) // 雙指標從頭和尾比較 for i,v := range vals[:n/2]{ if v != vals[n-1-i]{ return false } } return true } // 遞迴 func isPalindrome2(head *ListNode) bool { frontPointer := head var recursivelyCheck func(node *ListNode) bool recursivelyCheck = func(node *ListNode) bool { if node != nil{ if !recursivelyCheck(node.Next){ return false } if node.Val != frontPointer.Val{ return false } frontPointer = frontPointer.Next } return true } return recursivelyCheck(head) } // 反轉連結串列 func reversList(head *ListNode) *ListNode { var prev,cur *ListNode = nil,head for cur != nil{ nextTmp := cur.Next cur.Next = prev prev = cur cur = nextTmp } return prev } // 快慢指標找到前半部分連結串列尾節點 func endOfFirstHalf(head *ListNode) *ListNode { fast,slow := head,head // 快指標速度為慢指標兩倍,快指標走到盡頭,慢指標走一半 for fast.Next != nil && fast.Next.Next != nil{ fast = fast.Next.Next slow = slow.Next } return slow } // 快慢指標 func isPalindrome3(head *ListNode) bool { if head == nil{ return true } // 獲取前半部分連結串列尾節點 firstHalfEnd := endOfFirstHalf(head) // 反轉後半部分節點 secondHalfStart := reversList(firstHalfEnd.Next) // 與反轉後的後半部分連結串列比較判斷是否是迴文 p1,p2 := head,secondHalfStart result := true for result && p2 != nil{ if p1.Val != p2.Val{ result = false } p1 = p1.Next p2 = p2.Next } // 還原連結串列反轉 firstHalfEnd.Next = reversList(secondHalfStart) return result }