JZ8-题解 | #二叉树的下一个结点#

二叉树的下一个结点

http://www.nowcoder.com/practice/9023a0c988684a53960365b889ceaf5e

题目描述:

给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示.

alt

示例:
输入:{8,6,10,5,7,9,11},8
返回:9
解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来

alt


题解1:使用数组,将二叉树的中序遍历结果存放在数组中,直接寻找到某结点的下一个结点。

步骤:

  1. 寻找到二叉树的根节点。由于提供了指向父亲结点的指针,因此,当next == NULL时,为二叉树根节点。
  2. 中序遍历二叉树,并将结果存放在数组中。
  3. 找到当前结点,返回当前结点的下一个结点。

代码:

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
//中序遍历
void preOrder(TreeLinkNode * t,vector<TreeLinkNode *> &v){
    if(NULL == t) return;
    preOrder(t->left, v);//访问左子树
    v.push_back(t);//将根结点放入vector容器中
    preOrder(t->right, v);//访问右子树
}
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        if(NULL == pNode) return NULL;
        TreeLinkNode * temp = pNode;
        //寻找根节点
        while(temp->next != NULL){
            temp = temp->next;
        }
        //中序遍历二叉树,并将遍历结果存放在vector中
        vector<TreeLinkNode*> v;
        preOrder(temp, v);//从根节点开始遍历
        //直接在vector容器中找到该节点的下一个结点
        for(int i = 0 ; i < v.size(); i++){
            if(v[i] == pNode && i < v.size()){
                return v[++i];//结点i的下一个结点
            }
        }
        return NULL;
    }
};

题解2:最优解-引自牛客提霸


alt

红色数字是中序遍历的顺序。接下来,我们就假设,如果当前结点分别是1,2 ... 7,下一结点看有什么规律没?

1 => 2 // 显然下一结点是 1 的父亲结点
2 => 3 // 下一节点是当前结点右孩子的左孩子结点,其实你也应该想到了,应该是一直到左孩子为空的那个结点
3 => 4 // 跟 2 的情况相似,当前结点右孩子结点的左孩子为空的那个结点
4 => 5 // 5 是父亲结点 3 的父亲结点,发现和1有点像,因为 1,3,同样是父亲结点的左孩子
5 => 6 // 跟 4=>5 一样的道理
6 => 7 // 跟 3=>4 一样的道理
7 => null // 因为属于最尾结点

总结: 此时,可以总结一下:
[1] 是一类:特点:当前结点是父亲结点的左孩子
[2 3 6] 是一类,特点:当前结点右孩子结点,那么下一节点就是:右孩子结点的最左孩子结点,如果右孩子结点没有左孩子就是自己
[4 5]是一类,特点:当前结点为父亲结点的右孩子结点,本质还是[1]那一类
[7]是一类,特点:最尾结点


/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/

class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        if(NULL == pNode) return NULL;
        
        //若有右子树,寻找右子树的最左边孩子
        TreeLinkNode *temp =pNode->right;
       if(temp){
           while(temp->left != NULL)//始终指向左孩子
               temp = temp->left;
           return temp;
       }
        
        //若没有右子树,找最右父结点
        temp = pNode;
        while(temp->next){
            if(temp->next->left == temp){
                return temp->next;//找到了,返回下一个结点
            }
            temp = temp->next;
        }
        return NULL;
    }
};
全部评论

相关推荐

12-15 19:41
已编辑
广东工业大学 前端工程师
smile丶snow:尽量保证的一张a4纸吧。为什么工作经历只有公司?如果项目经历是工作里面的,应该写到工作经历里的吧。没有写项目职责,项目全是一个人写的吗?标题大小也好怪。两个项目的分割看不出来是,它和那些项目成功字体是一样大的
点赞 评论 收藏
分享
不知道怎么取名字_:玩游戏都写到简历上了啊
投递BOSS直聘等公司6个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务