234.回文链表
题目:请判断一个链表是否为回文链表。
思考:能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
分析:题目默认链表为单链表,因为链表与数组不同,数组支持随机访问,根据下标随机访问的时间复杂度为O(1),而链表为O(n)。我们无法通过首尾指针的方法判断是否为回文串。
解决思路:我们可以使用一种快慢指针的方法来进行判断。
快指针每次前进两个单位,慢指针每次前进一个单位并修改其next节点指向前一个节点,所以当快指针到达链表末尾的时候(空节点或空节点的前一个节点),慢指针刚好在中间,此时慢指针继续向后走,同时开辟一个新节点往前走,判断链表中点前后是否相同,达到判断回文串的目的。
应该注意的是,当链表长度奇偶不同时需要对慢节点进行微调,具体看代码。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode pre = null;//指向前一个节点的指针
ListNode slow = head;//慢指针
ListNode fast = head;//快指针
while(fast!=null&&fast.next!=null){
fast = fast.next.next;
ListNode next = slow.next;
slow.next = pre;//修改慢指针走过的节点指向前一个节点
pre = slow;
slow = next;
}
if(fast != null){
slow = slow.next;
//当长度为奇数是,慢指针需要再走一个单位
}
while(pre!=null) {
//判断是否为回文串
if(pre.val!=slow.val){
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}
这道题是我在学习王争老师的《数据结构与算法之美》的一道课后题,快慢指针的思路确实很巧妙,数组和链表这两种数据结构虽简单常用但也应该理解深入。若有表述错误或不清楚的请在评论区指正,谢谢。