题目

Given a singly linked list, determine if it is a palindrome.

Example 1:

  1. Input: 1->2
  2. Output: false

Example 2:

  1. Input: 1->2->2->1
  2. Output: true

Follow up:
Could you do it in O(n) time and O(1) space?


题意

判断一个链表的值是否构成回文。

思路

最简单的方法是遍历一遍链表将所有值存到数组中,再对数组进行处理。也可以用栈保存数值,利用栈的性质,出栈顺序即为链表的逆序遍历,只要再遍历一遍链表与出栈相比即可。

对上述方法的优化:利用快慢指针找到链表的中间结点,在此过程中将链表前半部分的值依次压入栈中,接着将慢指针继续向尾结点移动,同时不断出栈进行比较(出栈的值即为前半部分值得逆序)。

0234. Palindrome Linked List (E) - 图1#card=math&code=O%281%29)空间的方法:先利用快慢指针找到链表的中间结点,再将后半部分链表逆置,遍历比较逆置后的链表和前半部分链表即可。


代码实现

Java

栈1

  1. class Solution {
  2. public boolean isPalindrome(ListNode head) {
  3. if (head == null || head.next == null) {
  4. return true;
  5. }
  6. ListNode pointer = head;
  7. Deque<Integer> stack = new ArrayDeque<>();
  8. while (pointer != null) {
  9. stack.push(pointer.val);
  10. pointer = pointer.next;
  11. }
  12. pointer = head;
  13. while (pointer != null) {
  14. if (pointer.val != stack.pop()) {
  15. return false;
  16. }
  17. pointer = pointer.next;
  18. }
  19. return true;
  20. }
  21. }

栈2

  1. class Solution {
  2. public boolean isPalindrome(ListNode head) {
  3. if (head == null || head.next == null) {
  4. return true;
  5. }
  6. ListNode slow = head;
  7. ListNode fast = head;
  8. Deque<Integer> stack = new ArrayDeque<>();
  9. stack.push(slow.val);
  10. while (fast.next != null && fast.next.next != null) {
  11. fast = fast.next.next;
  12. slow = slow.next;
  13. stack.push(slow.val);
  14. }
  15. if (fast.next == null) {
  16. stack.pop();
  17. }
  18. while (slow.next != null) {
  19. slow = slow.next;
  20. if (stack.pop() != slow.val) {
  21. return false;
  22. }
  23. }
  24. return true;
  25. }
  26. }

逆置链表

  1. class Solution {
  2. public boolean isPalindrome(ListNode head) {
  3. if (head == null || head.next == null) {
  4. return true;
  5. }
  6. ListNode slow = head;
  7. ListNode fast = head;
  8. while(fast.next!=null&&fast.next.next!=null){
  9. fast = fast.next.next;
  10. slow = slow.next;
  11. }
  12. // 标记找到的中间结点(实际为前半部分的最后一个结点),并断开前后链表
  13. ListNode mid = slow;
  14. slow = slow.next;
  15. mid.next = null;
  16. // 逆置后半部分链表
  17. while (slow != null) {
  18. ListNode temp = slow.next;
  19. slow.next = mid.next;
  20. mid.next = slow;
  21. slow = temp;
  22. }
  23. ListNode firstHalf = head;
  24. ListNode secondHalf = mid.next;
  25. // 比较前后部分链表
  26. while (secondHalf != null) {
  27. if (firstHalf.val != secondHalf.val) {
  28. return false;
  29. }
  30. firstHalf = firstHalf.next;
  31. secondHalf = secondHalf.next;
  32. }
  33. return true;
  34. }
  35. }

JavaScript

  1. /**
  2. * @param {ListNode} head
  3. * @return {boolean}
  4. */
  5. var isPalindrome = function (head) {
  6. const dummy = new ListNode()
  7. let slow = head, fast = head
  8. while (fast && fast.next) {
  9. const tmp = slow.next
  10. fast = fast.next.next
  11. slow.next = dummy.next
  12. dummy.next = slow
  13. slow = tmp
  14. }
  15. let A = dummy.next, B = fast ? slow.next : slow
  16. while (A) {
  17. if (A.val !== B.val) return false
  18. A = A.next
  19. B = B.next
  20. }
  21. return true
  22. }