劍指offer(五)

21. 鏈表中環的入口節點

這是比較清晰的方式,但是面試時我應該想不出來這個規律,這也是看了別人的答案才知道這個規律的。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL || pHead->next==NULL) return NULL;
        ListNode* FHead=pHead;
        ListNode* SHead=pHead;
        while(FHead!=NULL && FHead->next!=NULL){
            FHead=FHead->next->next;
            SHead=SHead->next;
            if(FHead==SHead) break;
        }
        //不存在環,return null
        if(FHead==NULL || FHead->next==NULL) return NULL;
        //存在環,找入口節點
        //兩個指針第一次的相遇點到入口節點的距離等於頭節點到入口節點的距離(通過計算可得)
        FHead=pHead;
        while(FHead!=SHead){
            FHead=FHead->next;
            SHead=SHead->next;
        }
        return SHead;
 
    }
};

這是正常的思路,不用找規律,先求出環的長度,再用快慢指針找到入口點。

class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL || pHead->next==NULL) return NULL;
        ListNode* FHead=pHead;
        ListNode* SHead=pHead;
        while(FHead->next!=NULL && FHead!=SHead){
            FHead=FHead->next->next;
            SHead=SHead->next;
        }
        //不存在環,return null
        if(FHead==NULL || FHead->next==NULL) return NULL;
        //存在環,找入口節點
        //環長度等於quikspeed*step-slowspeed*step,step爲相遇時的step
        int length=0;
        if(FHead==SHead){
            int step=1;
            FHead=FHead->next->next;
            SHead=SHead->next;
            while(FHead!=SHead){
                step++;
                FHead=FHead->next->next;
                SHead=SHead->next;
            }
            length=step;
        }
        //求出環長度後利用快慢指針求環入口
        FHead=pHead;
        SHead=pHead;
        //快指針先走環長的長度,再兩個指針一起走,再相遇即是入口
        while(length--) FHead=FHead->next;
        while(FHead!=SHead){
            FHead=FHead->next;
            SHead=SHead->next;
        }
        return FHead;
    }
};

22. 反轉鏈表

下圖便於理解代碼思路

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL) return NULL;
        ListNode* back=NULL;
        ListNode* tmp=pHead;
        ListNode* pre=NULL;
        while(tmp!=NULL){
            pre=tmp->next;
            tmp->next=back;
            back=tmp;
            tmp=pre;
        }
        return back;

    }
};

22. 合併兩個排序的鏈表

最重要的是新鏈表初始化要注意,先給頭指針賦值,否則會出現溢出,段錯誤這樣的錯誤。

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==NULL && pHead2==NULL) return NULL;
        if(pHead1==NULL) return pHead2;
        if(pHead2==NULL) return pHead1;
        ListNode* NewHead=NULL;
        //給頭指針賦值
        if(pHead1->val<=pHead2->val){
            NewHead= new ListNode(pHead1->val);
            pHead1=pHead1->next;
        }
        else {
            NewHead= new ListNode(pHead2->val);
            pHead2=pHead2->next;
        }
        NewHead->next=NULL;
        ListNode* New=NewHead;
 
        while(pHead1!=NULL && pHead2!=NULL){
            if(pHead1->val<=pHead2->val){
                New->next=pHead1;
                New=New->next;
                pHead1=pHead1->next;
            }
            else{
                New->next=pHead2;
                New=New->next;
                pHead2=pHead2->next;
            }
        }
        if(pHead1==NULL) New->next=pHead2;
        else if(pHead2==NULL) New->next=pHead1;
        return NewHead;
    }
};

23. 樹的子結構

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        bool result=false;        
        if(pRoot2!=NULL && pRoot1!=NULL){
            //找根節點
            if(pRoot1->val==pRoot2->val)
                //匹配成功返回,不成功繼續找
                result=Match(pRoot1, pRoot2);
            if(!result)
                result=HasSubtree(pRoot1->left, pRoot2);
            if(!result)    
                result=HasSubtree(pRoot1->right, pRoot2);
        }   
        //如果爲NULL則直接返回false;
        return result;

    }
private:
    bool Match(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot2==NULL) return true;
        if(pRoot1==NULL) return false;
        if(pRoot1->val!=pRoot2->val) return false;
        return Match(pRoot1->left, pRoot2->left)&&Match(pRoot1->right, pRoot2->right);
    }
};

24. 二叉樹的鏡像

從根節點開始交換左右節點。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot==NULL) return;
        TreeNode *temp=pRoot->right;
        pRoot->right=pRoot->left;
        pRoot->left=temp;
        Mirror(pRoot->left);
        Mirror(pRoot->right);
        return;
    }
};

25. 對稱的二叉樹

class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(pRoot==NULL) return true;
        //對比左右子樹是否軸對稱
        return isSymme(pRoot->left,pRoot->right);
    
    }
private:
    bool isSymme(TreeNode* left,TreeNode* right){
        if(left==NULL && right==NULL) return true;
        else if(left==NULL || right==NULL) return false;
        if(left->val==right->val) 
            return isSymme(left->left,right->right)&&isSymme(left->right,right->left);
        return false;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章