问题:
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
解决:
① 使用一个链表记录前半段链表,比较后半段链表与该链表,若有不等则说明不是回文链表。采用快慢指针的方法判断中间节点,slow每次前进1步,fast每次前进2步,当fast到达尾部的时候,slow正好指向中间节点。时间复杂度O(n),空间复杂度O(n/2)。耗时56ms.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public static boolean isPalindrome(ListNode head) {
LinkedList<Integer> list = new LinkedList<>();
if(head == null || head.next == null) return true;
ListNode slow = head;
ListNode fast = head;
list.add(0,slow.val); //头插法
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow =slow.next;
list.add(0,slow.val);
}
ListNode cur = slow;
if(fast.next != null) cur = slow.next;//链表长度为偶数
int i = 0;
while(cur != null){
if(list.get(i) != cur.val) return false;
cur = cur.next;
i ++;
}
return true;
}
}
② 使用栈保存前半段。
public class Solution {
public static boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode slow = head;
ListNode fast = head;
if(head == null || head.next == null) return true;//0个节点或是1个节点
stack.push(slow);
while(fast.next!=null&&fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
stack.push(slow);
}
if(fast.next != null) slow = slow.next;//链表长度为偶数
ListNode cur = slow;
while(cur != null){
if(cur.val != stack.pop().val) return false;
cur=cur.next;
}
return true;
}
}
③ 将后半段链表原地反转,时间复杂度O(n),空间复杂度O(1)。耗时2ms.
public class Solution {
public static boolean isPalindrome(ListNode head) {
ListNode slow = head;
ListNode fast = head;
if(head == null || head.next == null)//0个节点或是1个节点
return true;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode midNode = slow;
ListNode firNode = slow.next;//后半段链表的第一个节点
ListNode cur = firNode.next;//插入节点从第一个节点后面一个开始
firNode.next = null;//第一个节点最后会变最后一个节点
while(cur != null){ //对链表后半段进行反转
ListNode nextNode = cur.next;//保存下次遍历的节点
cur.next = midNode.next;
midNode.next = cur;
cur = nextNode;
}
slow = head; //反转之后对前后半段进行比较
fast = midNode.next;
while(fast != null){
if(fast.val != slow.val)return false;
slow = slow.next;
fast = fast.next;
}
return true;
}
}