請判斷一個鏈表是否爲迴文鏈表。
示例 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迭代
}
}
}