判斷一個單向鏈結串列是否為迴文(palindrome)。
Ex.
方法 1:將鏈表轉成陣列 (Brute Force)
遍歷鏈表,把所有值存進 List。
用雙指針從頭尾比較。
時間複雜度:O(n)
空間複雜度:O(n)
簡單,但佔額外空間,不是最佳解
方法 2:快慢指針 + 反轉後半鏈表, 常見解法
時間複雜度:O(n)
空間複雜度:O(1)
方法 3:遞迴
利用遞迴「向內推進」並比較對稱節點。
class Solution {
fun isPalindrome(head: ListNode?): Boolean {
if (head?.next == null) return true
// 1. 找到中點
var slow = head
var fast = head
while (fast?.next != null && fast.next?.next != null) {
slow = slow?.next
fast = fast.next?.next
}
// 2. 反轉後半部分
var secondHalf = reverseList(slow?.next)
// 3. 比對前後半部分
var p1 = head
var p2 = secondHalf
while (p2 != null) {
if (p1?.`val` != p2.`val`) return false
p1 = p1?.next
p2 = p2.next
}
return true
}
private fun reverseList(head: ListNode?): ListNode? {
var prev: ListNode? = null
var curr = head
while (curr != null) {
val nextNode = curr.next
curr.next = prev
prev = curr
curr = nextNode
}
return prev
}
}