剑指offer14-17题思路及代码(输出倒数第k个结点,反转链表,合并两个排序的链表,树的子结构)

14输出倒数第k个结点
该题很多书都有涉及过,且leetcode第19题也是这道题目,其具体的想法是建立两个指针,一个指针先走多少步,然后第二个指针再走,当第一个指针到队尾的时候,即第二个指针为倒数第n个位置。话说本人又做了些并无太大意义的改编,即统计链表长度,然后算出倒数第几个节点,再让第二个指针移动,其实质上和第一种方法区别不大,但代码稍微有些变化。代码如下:
/*
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)
            return NULL;
        ListNode* nHead=pListHead;
        ListNode* p=pListHead;
        int num=0;
        while(nHead){
            num++;
            nHead=nHead->next;
        }
        if(num<k)
            return NULL;
        for(int i=0;i<num-k;i++)
            p=p->next;
        return p;
    }
};
15反转链表
看到题目以后写出了如下的代码:
/*
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 pHead;
        ListNode* pNew=pHead;
        pNew->next=NULL;
        while(pHead->next){
            ListNode* pNext=pHead->next;
            pNext->next=pNew;
            pNew=pNext;
            pHead=pHead->next;
        }
        return pNew->next;
    }
};
说实话是个愚蠢的想法,其实想法没毛病,新建一个指针指向链表头部,然后运用头插法把后面的元素一个一个插进去,不过事实上写出来有点愚蠢。pNew->=NULL; 直接把链表断开连接。。。我到底在想啥?????正确代码如下:
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL||pHead->next==NULL)
            return pHead;
        ListNode* pNew=pHead;
        ListNode* p=NULL;
        ListNode* pNext=pHead->next;
        while(pHead){
            pNew->next=p;
            if(pNext==NULL)
                break;
            p=pNew;
            pNew=pNext;
            pNext=pNext->next;
        }
        return pNew;
    }
};
所以到底需要一个pNext来记录下面指针的状态,同时需要保存之前的状态,就能够达到目的了。
16合并两个排序的链表
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2){
        ListNode* p=NULL;
        if(pHead1->val>pHead2->val){
            p=pHead2;
            pHead2=pHead2->next;
        }
        else{
            ListNode* p=pHead1;
            pHead1=pHead1->next;
        }
        ListNode* answer=p;
        while(pHead1&&pHead2){
            if(pHead1->val>pHead2->val){
                p->next=pHead2;
                pHead2=pHead2->next;
                p=p->next;
            }
            else{
                p->next=pHead1;
                pHead1=pHead1->next;
                p=p->next;
            }
        }
        if(!pHead1)
            p->next=pHead1;
        else
            p->next=pHead2;
        return answer;
    }
};

没看答案之前写出来了个这玩意。。。我也不知道这玩意是啥,反正又长可读性有差,新建了不知道多少个元素,然后发现直接编译不过。。。于是看了答案发现原来可以用递归来着。。。果然递归学得不好啊,想不到啊想不到。正确答案:
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2){
        if(pHead1==NULL)
            return pHead2;
        if(pHead2==NULL)
            return pHead1;
        ListNode* pReturn=NULL;
        if(pHead1->val<pHead2->val){
            pReturn=pHead1;
            pReturn->next=Merge(pHead1->next,pHead2);
        }
        else{
            pReturn=pHead2;
            pReturn->next=Merge(pHead1,pHead2->next);
        }
        return pReturn;
    }
};

17树的子结构
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2){
        bool result=false;
        if(pRoot1!=NULL&&pRoot2!=NULL){
            if(pRoot1->val==pRoot2->val)
            result=DoesTree1HaveTree2(pRoot1,pRoot2);
        if(!result)
            result=HasSubtree(pRoot1->left,pRoot2);
        if(!result)
            result=HasSubtree(pRoot1,pRoot2->left);   //改为result=HasSubtree(pRoot1->right,pRoot2);
        }
        return result;
    }
    bool DoesTree1HaveTree2(TreeNode* pRoot1,TreeNode* pRoot2){
        if(pRoot2==NULL)
            return true;
        if(pRoot1==NULL)
            return false;
        if(pRoot1->val!=pRoot2->val)
            return false;
        return DoesTree1HaveTree2(pRoot1->left,pRoot2->left)&&DoesTree1HaveTree2(pRoot1->right,pRoot2->right);
    }
};
仔细复查了一下,发现第三个判断写错了,应该是result=HasSubtree(pRoot1->right,pRoot2);,这样应该就没毛病了,果然粗心大意是硬伤啊


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值