Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2 Output: falseExample 2:
Input: 1->2->2->1 Output: true
Follow up:
Could you do it in O(n) time and O(1) space?
回文链表。题意是给一个链表,判断是不是回文链表。思路是快慢指针找到链表中点,reverse后半段,然后比较前半和后半。题目要求不能使用额外空间,其实是不太可能的,除非直接在input的链表上做操作。
二刷的时候有一个疑问,找到的链表中点,如果整个链表的节点数为奇数,中点在哪?节点数为偶数,中点又在哪?我跑了一个例子帮助加强记忆,如下图,图中数字表示节点的index。当找中间节点的函数跑完的时候,如果节点数是偶数个,则s停在3的位置;如果节点数是奇数个,则s停在2的位置。后半部分的head节点是slow.next所以后半部分的head节点分别是4和3(偶数,奇数)。
reverse后半部分,则对于第一个例子,比较的是123和654两个链表;对于第二个例子,比较的是12和543两个链表。又因为while循环的时候判断的是两个链表同时不为空,所以当链表节点个数为奇数的时候,也能判断input是否为回文链表。
1 - 2 - 3 - 4 - 5 - 6
s f
1 - 2 - 3 - 4 - 5
s f
时间O(n) - 题目要求
空间O(1) - 题目要求
JavaScript实现
1 /** 2 * @param {ListNode} head 3 * @return {boolean} 4 */ 5 var isPalindrome = function(head) { 6 if (head === null) return true; 7 let middle = findMiddle(head); 8 middle.next = reverse(middle.next); 9 10 let p = head; 11 let q = middle.next; 12 while (p !== null && q !== null) { 13 if (p.val !== q.val) { 14 return false; 15 } 16 p = p.next; 17 q = q.next; 18 } 19 return true; 20 }; 21 22 var findMiddle = function(head) { 23 let slow = head; 24 let fast = head.next; 25 while (fast !== null && fast.next !== null) { 26 slow = slow.next; 27 fast = fast.next.next; 28 } 29 return slow; 30 } 31 32 var reverse = function(head) { 33 let pre = null; 34 while (head !== null) { 35 let next = head.next; 36 head.next = pre; 37 pre = head; 38 head = next; 39 } 40 return pre; 41 }
最后注意代码里面24行定义fast pointer的方式。
Java实现
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode(int x) { val = x; } 7 * } 8 */ 9 class Solution { 10 public boolean isPalindrome(ListNode head) { 11 // corner case 12 if (head == null) { 13 return true; 14 } 15 // normal case 16 ListNode middle = findMiddle(head); 17 middle.next = reverse(middle.next); 18 ListNode p1 = head; 19 ListNode p2 = middle.next; 20 while (p1 != null && p2 != null) { 21 if (p1.val != p2.val) { 22 return false; 23 } else { 24 p1 = p1.next; 25 p2 = p2.next; 26 } 27 } 28 return true; 29 } 30 31 private ListNode findMiddle(ListNode head) { 32 ListNode slow = head; 33 ListNode fast = head; 34 while (fast.next != null && fast.next.next != null) { 35 slow = slow.next; 36 fast = fast.next.next; 37 } 38 return slow; 39 } 40 41 private ListNode reverse(ListNode head) { 42 ListNode pre = null; 43 while (head != null) { 44 ListNode next = head.next; 45 head.next = pre; 46 pre = head; 47 head = next; 48 } 49 return pre; 50 } 51 }
相关题目