234. 回文链表(双指针+链表逆转、递归)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
1、双指针+逆转链表
思想**
用双指针法找到指向中间节点的指针;再将后半部分链表逆转;
然后再用另一对双指针分别从头结点和中间节点往后遍历逐个进行比较即可
代码**
/**
* 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 p = head;//遍历至中间结点的指针
ListNode q = head;
ListNode l = head;//从前往中间结点去的指针
/*
while(q.next != null){
p = p.next;
q = q.next;
if(q.next != null){
q = q.next;
}
}
*/
while(q.next != null && q.next.next != null){
p = p.next;
q = q.next.next;
}
ListNode prer = null;
ListNode r = p.next;//右端链表的起始节点
p.next = null;
while(r != null){
ListNode tmp = r.next;
r.next = prer;
prer = r;
r = tmp;
}
r = prer;
while(l != null && r != null){
if(l.val != r.val){
return false;
}
else{
l = l.next;
r = r.next;
}
}
return true;
}
}
2、递归法
思想**
递归遍历时候,最先出结果的是最后的结点,可以用这个特性访问到链表尾与从表头开始的指针进行比较
代码**
/*
递归遍历时候,最先出结果的是最后的结点,可以用这个特性访问到链表尾与从表头开始的指针进行比较
*/
class Solution {
ListNode preNode;
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){//特殊边界处理
return true;
}
preNode = head;
return recursivelyCheck(head);//调用递归函数
}
public boolean recursivelyCheck(ListNode curNode) {
if(curNode != null){//特殊边界处理
if(!recursivelyCheck(curNode.next)){//递归下一级比较
return false;
}
if(curNode.val != preNode.val){//当前比较
return false;
}
preNode = preNode.next;//指向前半部分遍历的指针
}
return true;
}
}