美雜誌首次揭祕蘋果總部 Apple Park 內部:安靜、寧和、舒適
阿新 • • 發佈:2021-12-15
目錄
234.迴文連結串列
題目
給你一個單鏈表的頭節點 head ,請你判斷該連結串列是否為迴文連結串列。如果是,返回 true ;否則,返回 false 。
示例1
輸入:head = [1,2,2,1]
輸出:true
示例2
輸入:head = [1,2]
輸出:false
進階:你能否用 O(n) 時間複雜度和 O(1) 空間複雜度解決此題?
題解
迴文:abba,或者aba對稱的模式
一個最簡單的思路就是翻轉連結串列之後,比較對應位置是否相同。
這樣需要新建一個連結串列,也就是原連結串列的翻轉連結串列。這樣空間複雜度就不是1了。
可以不新建連結串列嗎?可以把原連結串列分成兩部分,一部分翻轉,一部分不翻轉,然後開始比較。
翻轉連結串列
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head != null){
tmp=head.next;
head.next = pre;
pre=head;
head=tmp;
}
return pre;
}
需要將連結串列分成兩部分,需要使用雙指標
- 情況1:abba slow指向的第一個b,fast指向的最後一個元素,需要翻轉ab
- 情況2:aba slow指向b,fast執行null,需要反轉a
//如果只有一個元素直接返回不用反轉 if(head.next==null) return true; //把連結串列分成兩個部分, ListNode slow = head; ListNode fast = head.next; while(fast!=null && fast.next!=null){ slow = slow.next; fast=fast.next.next; } //反轉連結串列 abba->abab babab->babba slow.next = reverseList(slow.next); //引數slow.next指向需要反轉的連結串列 fast = slow.next; //fast指向第二段連結串列的開頭 //開始判斷是否是迴文 while(fast!=null){ if(head.val != fast.val)return false; head = head.next; fast = fast.next; } return true;
程式碼
class Solution {
public boolean isPalindrome(ListNode head) {
if(head.next==null) return true;
ListNode slow = head;
ListNode fast = head.next;
//找到中間位置
while(fast!=null && fast.next!=null){
slow = slow.next;
fast=fast.next.next;
}
//後面的反轉
slow.next = reverseList(slow.next);
fast = slow.next;
//開始判斷是否是迴文
while(fast!=null){
if(head.val != fast.val)return false;
head = head.next;
fast = fast.next;
}
return true;
}
//反轉連結串列
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head != null){
tmp=head.next;
head.next = pre;
pre=head;
head=tmp;
}
return pre;
}
}
優化
這裡我們反轉的是中點後面的連結串列,並且後面的位置我們已經遍歷過了。
可不可以邊找中點的時候,邊反轉前面的連結串列?這樣走過的連結串列就不用再走了
if(head.next==null) return true;
ListNode slow = head;
ListNode fast = head;
ListNode pre = null;
ListNode tmp = head; //反轉時使用
//找到中間位置
while(fast!=null && fast.next!=null){
fast=fast.next.next; //fast先行,防止反轉後找不到位置。
tmp =slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
}
//退出的時候,如下圖所示:情況1的slow需要再走一步進行比較
if(fast!=null) slow=slow.next;
while(slow!=null){
if(pre.val!=slow.val) return false;
pre = pre.next;
slow = slow.next;
}
return true;