剑指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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章