题目
给定一个链表的头节点 head,请判断该链表是否为回文结构。
例如
1->2->1, 返回 true。
1->2->2->1, 返回 true。
15->6->15, 返回 true。
1->2->3, 返回 false。
进阶要求
如果链表长度为 N,时间复杂度要求达到 O(N),额外空间复杂度达到 O(1)。
解答
方法一
利用栈来判断,将所有节点压入栈中,然后弹出时就是按照逆序来弹出的,在弹出的同时与正序的原来的链表的相应的元素作比较,这样就很容易判断出是否是回文结构了。
1 2 3 4 5 6 7 8
| public class Node { public int value; public Node next;
public Node(int value) { this.value = value; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public boolean isPalindrome1(Node head) { Stack<Node> stack = new Stack<>(); Node cur = head; while (cur != null) { stack.push(cur); cur = cur.next; } while (head != null) { if (head.value != stack.pop().value) { return false; } head = head.next; } return true; }
|
方法一的时间复杂度为 $O(N)$,额外空间复杂度为 $O(N)$。
方法二
这个方法本质上和方法一没有区别,只是,这个压栈操作有些变化,方法一是将所有的元素全部压入一个栈中,而这个方法则是先将栈给对半切割了,然后只是将右半部分的元素给压栈,然后再弹出和原链表的左半部分元素进行比较。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public boolean isPalindrome2(Node head) { if (head == null || head.next == null) { return true; } Node right = head.next; Node cur = head; while (cur.next != null && cur.next.next != null) { right = right.next; cur = cur.next.next; } Stack<Node> stack = new Stack<>(); while (right != null) { stack.push(right); right = right.next; } while (!stack.isEmpty()) { if (head.value != stack.pop().value) { return false; } head = head.next; } return true; }
|
方法二的时间复杂度为 $O(N$,额外空间复杂度为 $O(N)$。
方法三
方法三的主要思想是将链表从中间截断,然后使中间节点指向 null
,然后逆转右半部分的链表,然后左边和右边分别并同时从最左边的和最右边的节点进行遍历,比较它们每一个节点是否相同。最后,要将逆转的链表恢复原状。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public boolean isPalindrome3(Node head) { if (head == null || head.next == null) { return true; } Node n1 = head; Node n2 = head; while (n2.next != null && n2.next.next != null) { n1 = n1.next; n2 = n2.next.next; } n2 = n1.next; n1.next = null; Node n3 = null; while (n2 != null) { n3 = n2.next; n2.next = n1; n1 = n2; n2 = n3; } n3 = n1; n2 = head; boolean res = true; while (n1 != null && n2 != null) { if (n1.value != n2.value) { res = false; break; } n1 = n1.next; n2 = n2.next; } n1 = n3.next; n3.next = null; while (n1 != null) { n2 = n1.next; n1.next = n3; n3 = n1; n1 = n2; } return res; }
|