152. Palindrome Linked List(回文链表)
题目:
Given a singly linked list, determine if it is a palindrome.
给出一个单链表,确定它是否是回文。
Example 1:
Input: 1->2 Output: false
Example 2:
Input: 1->2->2->1 Output: true
Follow up:
Could you do it in O(n) time and O(1) space?
你能在O(n)时间和O(1)空间做吗?
解答:
方法一:
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 if(head==null || head.next==null) return true; 12 ListNode fast=head,slow=head; 13 Stack<Integer> stack=new Stack<>(); 14 stack.push(head.val); 15 while(fast.next!=null && fast.next.next!=null){ 16 fast=fast.next.next; 17 slow=slow.next; 18 stack.push(slow.val); 19 } 20 if(fast.next==null){//奇数,弹出最中间的数字 21 stack.pop(); 22 } 23 while(slow.next!=null){ 24 slow=slow.next; 25 if(stack.pop()!=slow.val) 26 return false; 27 } 28 return true; 29 } 30 }
方法二:
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 if(head==null || head.next==null) return true; 12 ListNode fast=head,slow=head; 13 while(fast!=null && fast.next!=null){ 14 fast=fast.next.next; 15 slow=slow.next; 16 } 17 if(fast!=null) 18 slow=slow.next;//奇数节点,让右半边小一点 19 slow=reverse(slow); 20 fast=head; 21 while(slow!=null){ 22 if(fast.val!=slow.val) 23 return false; 24 fast=fast.next; 25 slow=slow.next; 26 } 27 return true; 28 } 29 30 public ListNode reverse(ListNode head){ 31 ListNode newHead=null; 32 ListNode p=head; 33 while(p!=null){ 34 ListNode temp=p.next;//temp是p的下一个 35 p.next=newHead; 36 newHead=p;//newHead是第一个 37 p=temp;//p是newHead的下一个 38 } 39 return newHead; 40 } 41 }
详解:
快慢指针找中点,每次fast走两步,slow走一步,fast走到头,slow所指的位置即为中点。
思路一:利用栈。慢指针走一步,就把值压入栈中,走到中点后,链表前半段存入栈中,然后依次弹出比较后半段即可。
思路二:题目要求O(1)的空间,则不能依靠栈。那么在找到中点后,就把后半段链表反转,与前半段比较即可。