《程序員面試經典》——鏈表

部分文字代碼copy模仿,如有雷同,請勿介意小白記錄敲代碼的過程。

1.鏈表中倒數第k個結點

輸入一個鏈表,輸出該鏈表中倒數第k個結點。

思路:快慢指針,前一個指針比後一個指針慢k步。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==NULL||k==0)return NULL;
        ListNode* phead=pListHead,*ptail=pListHead;;
        for(int i=1;i<k;++i){
            if(phead->next!=NULL){
                phead=phead->next;
            }else{
                return NULL;
            }
        }
        while(phead->next!=NULL){
            phead=phead->next;
            ptail=ptail->next;
        }
        return ptail;
    }
};

2.訪問單個節點的刪除

實現一個算法,刪除單向鏈表中間的某個結點,假定你只能訪問該結點。

給定待刪除的節點,請執行刪除操作,若該節點爲尾節點,返回false,否則返回true

思路:不刪這個節點了,把下個節點值copy過來,然後刪除下個節點

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Remove {
public:
    bool removeNode(ListNode* pNode) {
        // write code here
        if(pNode==NULL)return NULL;
        if(pNode->next==NULL){
            delete pNode;
            return false;
        }else{
            ListNode* newnode;
        newnode=pNode->next;
        pNode->val=newnode->val;
        pNode->next=newnode->next;
        delete newnode;
        return true;
        }
    }
};

3.鏈表分割

編寫代碼,以給定值x爲基準將鏈表分割成兩部分,所有小於x的結點排在大於或等於x的結點之前

給定一個鏈表的頭指針 ListNode* pHead,請返回重新排列後的鏈表的頭指針。注意:分割以後保持原來的數據順序不變。

思路:創建小數鏈表和大數鏈表,最後完成後將兩鏈表連接,注意頭結點也有值,需要進行比較。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        ListNode* small=new ListNode(0);
        ListNode* large=new ListNode(0);
        ListNode* smallhead=small;
        ListNode* largehead=large;
        while(pHead){
            if(pHead->val<x){
                small->next=pHead;
                small=small->next;
            }else{
                large->next=pHead;
                large=large->next;
            }
            pHead=pHead->next;
        }
        large->next=NULL;
        
        small->next=largehead->next;
        return smallhead->next;
        
    }
};

4.鏈式A+B

有兩個用鏈表表示的整數,每個結點包含一個數位。這些數位是反向存放的,也就是個位排在鏈表的首部。編寫函數對這兩個整數求和,並用鏈表形式返回結果。

給定兩個鏈表ListNode* A,ListNode* B,請返回A+B的結果(ListNode*)。

測試樣例:

{1,2,3},{3,2,1}
返回:{4,4,4}

思路:對應位相加,注意是否有進位,最後返回鏈表長的那個做爲結果。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Plus {
public:
    ListNode* plusAB(ListNode* a, ListNode* b) {
        // write code here
        ListNode* newlist=new ListNode(0);
        ListNode* p=newlist;
        ListNode* node;
        int c=0;
        int sum;
        int val1,val2;
        while(a!=NULL || b!=NULL || c!=0){
            val1 = (a == NULL ? 0 : a->val);
            val2 = (b == NULL ? 0 : b->val);
            sum = val1 + val2 + c;
            c = sum / 10;
            node = new ListNode(sum % 10);
            
            p->next=node;
            p=node;
            a=(a == NULL ? NULL : a->next);
            b=(b == NULL ? NULL : b->next);
        }
        return newlist->next;
    }
};

5.迴文鏈表

請編寫一個函數,檢查鏈表是否爲迴文。

給定一個鏈表ListNode* pHead,請返回一個bool,代表鏈表是否爲迴文。

測試樣例:

{1,2,3,2,1}
返回:true
{1,2,3,2,3}
返回:false

思路:

1>反轉鏈表:可以將原始鏈表反轉,判斷反轉以後的鏈表與原始鏈表是否完全一致,如果一致便返回true,如果不一致則返回false。反轉鏈表需要額外的存儲空間,不是特別優秀的方法。

2>棧實現:我們可以想到從中間節點向兩側開始比較,如果全部相同,則返回true,否則返回false,因爲無法獲得一個節點的前一個節點,這個時候我們可以想到用棧實現,先將鏈表前半部分的元素分別壓入堆棧,然後在遍歷後半部分元素的時候同時和棧頂元素進行比較,如果全部相等則返回true,否則返回false。

 特別注意:因爲我們不知道鏈表的的長度,可以通過快慢指針(一個指針每次移動兩個,一個指針每次移動一個)來找到中間元素,這樣整體只需要遍歷鏈表一次,所需要的棧空間縮小爲方法1的一半。

3>遞歸:遞歸方法分爲尾部遞歸和首部遞歸,還有中間遞歸,一般的尾部遞歸都可以用循環來實現,對於我們這道題目,遞歸的時候無法比較第一個元素和最後一個元素,即使知道最後一個元素,也無法獲得最後一個元素的前一個元素。所以我們選擇首部遞歸,先遞歸直到中間的元素,然後比較中間的元素,把比較結果返回,同時保存後半部分下一個要比較的元素(用引用傳遞可以,用二級指針也可以),遞歸返回後,如果是true,則繼續比較,如果是false,則直接返回false。

方法一:
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
         if (pHead == NULL)return false;
        ListNode* reverselist=new ListNode(0);
        ListNode* pa=pHead;
        ListNode* pb;
        reverselist->next=NULL;
        while(pa!=NULL){
            pb=new ListNode(pa->val);
            pb->next=reverselist->next;
            reverselist->next=pb;
            pa=pa->next;
        }
        pa=pHead;
        pb=reverselist->next;
        while(pa!=NULL&&pb!=NULL){
            if(pa->val==pb->val){
                pa=pa->next;
                pb=pb->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
        stack<int> s;
        if(pHead==NULL)return false;
        ListNode* p=pHead;
        ListNode* q=pHead;
        s.push(p->val);
        while(q->next!=NULL&&q->next->next!=NULL){
            p=p->next;
            s.push(p->val);
            q=q->next->next;
        }
        
        if(q->next==NULL){
            s.pop();
        }
        while(p->next!=NULL){
            p=p->next;
            if(p->val==s.top()){
                s.pop();
            }
            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 *tail=pHead;
        int length=0;
        while(tail!=NULL){
            length++;
            tail=tail->next;
        }
        return ispd(pHead,&tail,length);
    }
    
    bool ispd(ListNode* pHead,ListNode** tail,int length){
        if(length==0||pHead==NULL){
            return true;
        }
        if(length==1){
            *tail=pHead->next;
            return true;
        }
         if(length==2){
             if(pHead->val==pHead->next->val){
                 *tail=pHead->next->next;
                 return true;
             }else{
                 return false;
             }
           
        }
        bool flag=ispd(pHead->next,tail,length-2);
        if(flag==false)return false;
         ListNode* tail1=*tail;
        if(pHead->val==tail1->val){
                 *tail=tail1->next;
                 return true;
             }else{
                 return false;
             }
    }
};

 

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