题目地址:https://leetcode.com/problems/palindrome-linked-list/
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?
判断一个链表是不是回文的,这个题目的难度在单链表不能反向遍历,如果能反向遍历的话那就简单多了,既然不能反向遍历,那只能硬办法了。
我们也可以把链表中val域读出来放在数组中,然后再看数组中的数值是不是回文的,但是题目只限制我们原地搞定这个问题,那咋办。
我们想起了前面写到过链表翻转的代码,好有了这个就好办了:
- 遍历一次链表,确定链表的长度,这是O(n)的时间复杂度;
- 根据链表的长度,以中间节点为分界线,截取前后两部分为两个链表,花费O(n/2)的时间;
- 把后面的这个链表翻转一下,这是O(n/2)的时间;
- 最后比较这两个链表数据域是否相等,又是O(n/2)的时间。
四个步骤下来,总的时间复杂度还是O(n),符合题意,而且也是原地操作,也满足O(1)的空间,代码实现如下:
public class PalindromeLinkedList {
public static boolean isPalindrome(ListNode head) {
if (head == null || head.next == null)
return true;
// get the length of the list
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
int halfLen = len / 2;
ListNode preHalf = null, postHalf = null;
// divide the list into 2 parts
if (len % 2 == 0) {
p = head;
for (int i = 0; i < halfLen - 1; i++) {
p = p.next;
}
ListNode q = p.next;
p.next = null;
preHalf = head;
postHalf = q;
} else {
p = head;
for (int i = 0; i < halfLen - 1; i++) {
p = p.next;
}
ListNode q = p.next.next;
p.next = null;
preHalf = head;
postHalf = q;
}
postHalf = reverseList(postHalf);
p = preHalf;
ListNode k = postHalf;
// compare the 2 lists
for (; p != null && k != null; p = p.next, k = k.next) {
if (p.val != k.val)
return false;
continue;
}
if (p == null && k == null)
return true;
return false;
}
public static ListNode reverseList(ListNode head) {
if (head == null)
return head;
ListNode p = new ListNode(head.val);
ListNode q = head.next;
while (q != null) {
ListNode t = new ListNode(q.val);
t.next = p;
p = t;
q = q.next;
}
return p;
}
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
node1.next = new ListNode(2);
node1.next.next = new ListNode(1);
//node1.next.next.next = new ListNode(5);
//node1.next.next.next.next = new ListNode(2);
//node1.next.next.next.next.next = new ListNode(2);
//node1.next.next.next.next.next.next = new ListNode(1);
//node1.next.next.next.next.next.next.next = new ListNode(1);
System.out.print(isPalindrome(node1));
}
}