剑指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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值