题面
题目:判断一个链表是否为回文链表。
示例:
题目解析
回文链表是以中间为轴,两边中心对称的一个链表。
思路:
- 创建一个链表newList,将原始链表List的值逆序保存到newList中,再重新遍历两个链表并且按顺序比较元素的值,只要有一个位置的元素值不一样,就不是回文链表。
优化:
- 可以只反转一半的元素。先遍历一遍得到总长度,第二次遍历到达一半的位置后不再反转,开始比较两个链表。
- 可以使用双指针思想里的快慢指针,fast 一次走两步,slow 一次走一步。当 fast 到达表尾时,slow 正好到达链表一半的位置。接下来可以从头开始逆序一半的元素,或者从 slow 开始逆序一半的元素即可。
代码实现如下:
public static boolean isPalindromeByTwoPoints(ListNode head) {
if(head == null || head.next == null) {
return true;
}
ListNode slow = head, fast = head;
ListNode pre = head, prepre = null;
while (fast != null && fast.next != null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
pre.next = prepre;
prepre = pre;
}
if (fast != null) {
slow = slow.next;
}
while (pre != null && slow != null) {
if(pre.val != slow.val) {
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
通俗的来说,当fast走到链表尾部时slow在链表的中间,if语句块表示的则是当链表结点个数为偶数个时,slow指向后一个结点。第二个while表示slow到达中点位置,pre在中点前一个位置,pre的方向可看作从右向左,此时slow和pre可以分别看作两个新链表的起点,由原链表的中间同时向两边比较结点的值,从而判断出是否为回文链表。