请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
-
find中间节点,标记为 p、q或p、mid_node、q,
-
从head开始遍历,到p位置时比较p、q,然后回溯指向pre,同时q迭代指向next
-
可以在进入循环前判断p、q值是否相等,效率更高
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
ListNode list;//记录表头
ListNode p ;//开始回溯标记
ListNode q ;//开始迭代标记
boolean ret = true;
public boolean isPalindrome(ListNode head) {
/**
1、双指针找到中间节点
2、判断是偶数还是奇数?
3、pre回溯,cur迭代
*/
if(head == null || head.next == null){
return true;
}
list = head;
ListNode dummy = new ListNode(-1);//虚头,找到的中间节点可以用于奇数个节点和偶数个节点
dummy.next = head;
ListNode pre = dummy;
ListNode cur = dummy;
while(cur != null && cur.next != null && cur.next.next != null){
cur = cur.next.next;
pre = pre.next;
}
cur = pre.next;
ListNode copy = pre;//copy一份用于奇数测试
p = pre;
q = pre.next;
isPal(head);//test偶数
if(!ret){//偶数未通过test奇数
p = copy;
if(p.next == null || p.next.next == null ){
return false;
}
q = p.next.next;//对称找到p、q
ListNode tmp = dummy.next;
ret = true;//重置ret
isPal(tmp);
}
return ret;
}
void isPal(ListNode head){
if(head != p){
isPal(head.next);//dfs
}
if(head.val != q.val){//从标记位置p开始比较p、q节点
ret = false;
return ;
}else{
if(q.next == null && head != list){//当cur迭代到尾时,判断pre是否回溯到表头
ret = false;
return ;
}
q = q.next;//p回溯q迭代
}
}
}