leetcode234_迴文鏈表

一. 迭代

1. 邊移動快慢指針邊反轉鏈表的前半部分,等找到鏈表中點,再將前半部分與後半部分依次比較,判斷是否爲迴文鏈表.

//大佬的思路, 反轉後半部分.
class Solution {
public:
    //題解:快慢指針法,快指針走兩步,慢指針走一步,找到鏈表的中點。然後,翻轉後半部分。最後從頭、中點開始判斷是否相同。
    bool isPalindrome(ListNode* head) {
        if(!head||!head->next)return true;
        ListNode *fast=head,*slow=head,*pre=nullptr;
        //1、找到鏈表的中點,鏈表長度奇偶不影響
        while(fast&&fast->next){
            slow=slow->next;
            fast=fast->next->next;
        }
        //2、將slow之後鏈表進行斷開且反轉,最後翻轉完成之後pre指向反轉鏈表的頭節點
        while(slow){
            ListNode *p=slow->next;
            slow->next=pre;
            pre=slow;
            slow=p;
        }
        //3、前後鏈表進行比較,注意若爲奇數鏈表,後半部分回比前部分多1一個節點,然而我們只比較相同長度的節點值,巧妙地避開這點判斷
        while(head&&pre){
            if(head->val!=pre->val)return false;
            head=head->next;
            pre=pre->next;
        }
        return true;
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

//自己的方法,邊移動邊反轉前半部分的鏈表.
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head==NULL || head->next==NULL) return true;
        ListNode* pre = NULL;
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast!=NULL && fast->next!=NULL) {
            //fast必須放在前面,因爲slow後會反轉鏈表,
            //造成fast->next取不到正確的.
            fast = fast->next->next;
            ListNode* tmp = slow->next;
            slow->next = pre;
            pre = slow;
            slow = tmp;
        }
        //畫圖可知, 當偶數時是正確的,奇數時需要slow往前next,這樣正好比較
        //相同的數字.
        if(fast!=NULL && fast->next==NULL) slow = slow->next;
        while(slow!=NULL) {
            if(slow->val!=pre->val) return false;
            slow = slow->next;
            pre = pre->next;
        }
        return true;
    }
};

二. 遞歸

1. 我自己的遞歸方法,特別慢.

class Solution {
public:
    ListNode* findLast(ListNode* head, int len) {
        if(len==1) return head;
        if(len==2) return head->next;
        ListNode* last = findLast(head->next, len-2);
        return last->next;
    }
    bool isPalindromeN(ListNode* head, int len) {
        //遞歸終止.
        if(len==0 || len==1) return true;
        //head->next,len-2長度是否迴文.
        bool flag = isPalindromeN(head->next, len-2);
        //找到末尾節點,進行比較.
        ListNode* last = findLast(head, len);
        if(head->val==last->val) return flag;
        else return false;
    }
    bool isPalindrome(ListNode* head) {
        if(head==NULL || head->next==NULL) return true;
        ListNode* cur = head;
        int len = 0;
        //求出鏈表長度
        while(cur!=NULL) {
            len++;
            cur = cur->next;
        }
        //函數作用返回head頭結點,len長度鏈表是否迴文.
        return isPalindromeN(head, len);
    }
};

2. 參考官方的.

class Solution {
public:
    ListNode* front = NULL;
    bool isPalindromeCheck(ListNode* head) {
        //遞歸終止.
        if(head==NULL) return true;
        //如果不滿足迴文,直接false.
        if(!isPalindromeCheck(head->next)) return false;
        //依次比較尾部節點和頭結點判斷是否迴文.
        if(head->val!=front->val) return false;
        //更新頭結點.
        front = front->next;
        return true;
    }
    bool isPalindrome(ListNode* head) {
        if(head==NULL || head->next==NULL) return true;
        //定義一個頭結點用於比較.
        front = head;
        return isPalindromeCheck(head);
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章