1. 程式人生 > >三種方法判斷連結串列是否為迴文結構

三種方法判斷連結串列是否為迴文結構

判斷連結串列是否是迴文結構:如1->2->3->2->1則是迴文結構

目錄

方法1:時間複雜度O(n),空間複雜度O(N),使用N個額外空間 最簡單

方法2:時間複雜度O(n),空間複雜度O(N),使用N/2個額外空間

方法3:時間複雜度O(n),空間複雜度O(1),最優解


方法1:時間複雜度O(n),空間複雜度O(N),使用N個額外空間 最簡單

將連結串列元素壓入棧,遍歷連結串列的同時彈出棧元素,判斷遍歷結點和彈出結點的值是否相等,如都相等,則是迴文結構。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        ListNode * p = pHead;
        stack<int> s;
        if(pHead == NULL ||pHead->next == NULL)
            return false;
        while(p){
            s.push(p->val);
            p=p->next;
        }
        ListNode *t = pHead;
        while(!s.empty()){
            if(t->val != s.top()){
                return false;
            }
            else{
                s.pop();
                t=t->next;
            }
        }
        return true;
    }
};

方法2:時間複雜度O(n),空間複雜度O(N),使用N/2個額外空間

用快慢指標遍歷連結串列,快指標一次走兩步,慢指標一次走一步,慢指標遍歷時將遍歷過的結點壓入棧中,快指標走完的時候,慢指標到達連結串列中間,棧頂到棧底是連結串列前半部分的逆序。

如果是奇數個元素,慢指標當前指向值(也就是中間位置)不壓入棧中,偶數個元素時,慢指標當前指向值也要壓入棧中。

慢指標繼續遍歷,同時棧元素彈出,若慢指標到達連結串列尾部,棧元素和慢指標遍歷位置元素都相等,則連結串列是迴文結構。

整個過程相當於把連結串列左邊折過來和連結串列右邊進行比較。

注意連結串列元素為奇數個和偶數個之間處理上的不同。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        ListNode * fast = pHead;
        ListNode * slow = pHead;
        stack<int> s;
       
        if(pHead == NULL ||pHead->next == NULL)
            return false;
        while(fast && fast->next){
            s.push(slow->val);
           
            slow = slow->next;
            fast = fast->next->next;
        }
           ListNode * p ;
////這裡有差別
          if (fast== NULL)//連結串列個數為偶數
			p = slow;
			
		else
			p = slow->next;
////
        while(p && !s.empty()){
            if(s.top()==p->val){
                s.pop();
                p= p->next;
            }
            else
                return false;
        }
        return true;
    }
};

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        ListNode * fast = pHead;
        ListNode * slow = pHead;
        stack<int> s;
       
        if(pHead == NULL ||pHead->next == NULL)
            return false;
        while(fast && fast->next){
            s.push(slow->val);
           
            slow = slow->next;
            fast = fast->next->next;
        }
           ListNode * p = slow;
////這裡有差別
          if (fast!= NULL)//連結串列個數為奇數
			 s.push(slow->val);
///
        while(p && !s.empty()){
            if(s.top()==p->val){
                s.pop();
                p= p->next;
            }
            else
                return false;
        }
        return true;
    }
};

方法3:時間複雜度O(n),空間複雜度O(1),最優解

找到連結串列中間值,連結串列右半部分做逆序。從連結串列兩段開始進行比較,如果兩個指標相遇前,對應元素都相等,則是迴文結構。

注意在做逆序的時候 ,設定逆序之後右邊連結串列的最後一個元素的next指向null,並以此作為迴圈判斷條件。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        ListNode* fast  = pHead;
        ListNode* slow  = pHead;
        while(fast&&fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode *res = NULL;//逆序時遍歷值
        ListNode *next;
        ListNode* p = pHead;
        while(slow){
            next = slow->next;
            slow->next = res;
            res = slow;
            slow = next;
        }
        while(res){
            if(p->val == res->val){
                p=p->next;
                res = res->next;
            }
            else{
                return false;
            }
            
        }
        return true;
        
    }
};