Problem:
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?
题目:给定一个单链表,判断是否为回文?最好时间复杂度O(n),空间复杂度为 O(1)。
思路:除去要求,最简单的方法则是用stack存储第一次遍历过的点,再第二次遍历依次取出比较。即可;此时空间复杂度为O(n);
满足要求的解法:将后半部分链表逆转,指向中间节点。再两端同时比较。最后最好将链表恢复成原始状态;
代码1:利用stack
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
Stack<Integer> stack = new Stack<Integer>();
ListNode node = head;
while(node!=null){
stack.push(node.val);
node=node.next;
}
node = head;
while(node!=null){
//int top = stack.pop();
if(stack.pop()!=node.val)
return false;
node=node.next;
}
return true;
}
}
代码2:满足时间复杂度O(n)和空间复杂度要求O(1)
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null)
return true;
ListNode node = head;
//ListNode right = null;
ListNode cur = head;
while (cur.next != null && cur.next.next != null) {
cur = cur.next.next;
node = node.next;
}
cur = node.next;
node.next = null;
ListNode temp=null;
while(cur!=null){
temp=cur.next;
cur.next=node;
node=cur;
cur=temp;
}
temp = node; //保存右区首节点
cur = head;
boolean ret = true;
while(cur!=null&&node!=null){
if(cur.val!=node.val){
ret = false;
break;
}
cur=cur.next;
node=node.next;
}
/*
cur=temp.next;
temp.next=null;
node = temp;
//恢复链表原始状态
while(cur!=null){
temp=cur.next;
cur.next=node;
node = cur;
cur = temp;
}*/
return ret;
}
}