回文链表
https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnv1oc/
https://leetcode-cn.com/problems/palindrome-linked-list/solution/
栈
把所有值存到栈(数组)中,然后前后指针来检查是否为回文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | func isPalindrome(head *ListNode) bool {     values := []int{}
      for head != nil {         values = append(values, head.Val)         head = head.Next     }
      n := len(values)     for i, v := range values[:n/2] {         if v != values[n-1-i] {             return false         }     }
      return true }
 
  | 
 
快慢指针
使用快慢指针,慢指针走 1 步时快指针走 2 步,这样在快指针到达末尾时,慢指针恰好在链表的中间。
反转后半部分链表,然后检查是否是回文,这样时间复杂度还是 O(n),空间复杂度只有 O(1)了。
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 32 33 34 35 36 37 38 39 40 41
   | func isPalindrome(head *ListNode) bool {     if head.Next == nil {         return true     }
      fast, slow := head, head
      for fast != nil && fast.Next != nil {         slow = slow.Next         fast = fast.Next.Next     }
      if fast != nil {          slow = slow.Next      }
      revHead := reverse(slow)
      for revHead != nil {         if head.Val != revHead.Val {             return false         }         head = head.Next         revHead = revHead.Next     }     return true }
  func reverse(head *ListNode) *ListNode {     var prev *ListNode     curr := head
      for curr != nil {         next := curr.Next         curr.Next = prev         prev = curr         curr = next     }
      return prev }
 
  | 
 
递归
类似于二叉树的后序遍历,单链表也能从后往前遍历,只要在调用递归函数之后进行访问操作就可以了,例如:(JAVA)
1 2 3 4 5 6
   | private void printListNode(ListNode head) {     if (head == null)         return;     printListNode(head.next);     System.out.println(head.val); }
 
  | 
 
因此也可以在递归中从后往前走的时候,用一个全局变量来储存从前往后走的指针,递归每走一步,这个指针也往前走一步,这样就能实现两头的访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | var temp *ListNode
  func isPalindrome(head *ListNode) bool {     temp = head     return check(head) }
  func check(node *ListNode) bool {     if node == nil {         return true     }     res := check(node.Next) && node.Val == temp.Val     temp = temp.Next          return res }
 
  | 
 
可以把递归视作函数调用栈,因此空间复杂度依然是 O(n)。