1. 程式人生 > 資訊 >美雜誌首次揭祕蘋果總部 Apple Park 內部:安靜、寧和、舒適

美雜誌首次揭祕蘋果總部 Apple Park 內部:安靜、寧和、舒適

目錄

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;