首页 > 试题广场 >

二叉树的下一个结点

[编程题]二叉树的下一个结点
  • 热度指数:466090 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示

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

要求:空间复杂度 ,时间复杂度

输入描述:
输入分为2段,第一段是整体的二叉树,第二段是给定二叉树节点的值,后台会将这2个参数组装为一个二叉树局部的子树传入到函数GetNext里面,用户得到的输入只有一个子树根节点


输出描述:
返回传入的子树根节点的下一个节点,后台会打印输出这个节点
示例1

输入

{8,6,10,5,7,9,11},8

输出

9
示例2

输入

{8,6,10,5,7,9,11},6

输出

7
示例3

输入

{1,2,#,#,3,#,4},4

输出

1
示例4

输入

{5},5

输出

"null"

说明

不存在,后台打印"null"   

说明:本题目包含复杂数据结构TreeLinkNode,点此查看相关信息
推荐
分析二叉树的下一个节点,一共有以下情况:
1.二叉树为空,则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。代码如下:
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(pNode==NULL)
            return NULL;
        if(pNode->right!=NULL)
        {
            pNode=pNode->right;
            while(pNode->left!=NULL)
                pNode=pNode->left;
            return pNode;
        }  
        while(pNode->next!=NULL)
        {
            TreeLinkNode *proot=pNode->next;
            if(proot->left==pNode)
                return proot;
            pNode=pNode->next;
        }
        return NULL;
    }
};
编辑于 2015-08-25 11:16:07 回复(49)
function GetNext(pNode) {
  if(!pNode) {
    return null;
  }
  // 存在右孩子,则返回右子树中最左节点
  if(pNode.right) {
    pNode = pNode.right;
    while(pNode.left) {
      pNode = pNode.left;
    }
    return pNode;
  } else {
    while(pNode) {
      // 中序遍历最后一个节点没有下一个节点
      if(pNode.next===null) {
        return null;
      // 节点是其父亲节点的左孩子,则直接返回其父亲节点
      }else if(pNode === pNode.next.left) { 
        return pNode.next;
      }
      // 节点是其父亲节点的右孩子,往上蹭分析
      pNode = pNode.next;
    }
    return pNode;
  }
}

发表于 2021-12-08 22:01:04 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
//暴力解法
let mydata=[]
function GetNext(pNode)
{    
    //传入的第一个节点就是我们要求的节点的父节点 而并不是树的真正根节点
    let firstnode=pNode
    //保存传入的节点
    let temp=pNode
    //递归父树直到根节点 
    while(temp.next!=null){
        temp=temp.next
    }
    //传入真正的根节点 中序遍历保存结果
    getmydata(temp)
    //保存要返回的结果
    let finaldata=null
    //遍历中序树的数组
    mydata.forEach((v,i)=>{
        if(v==firstnode){
                       //返回要求节点的下一个节点 
           finaldata= mydata[i+1]
        }
    })
    
    return finaldata
}
//中序遍历
function getmydata(pNode){
    if(!pNode) return 
    getmydata(pNode.left)
    mydata.push(pNode)
    getmydata(pNode.right)
}

module.exports = {
    GetNext : GetNext
};

发表于 2021-09-13 20:42:46 回复(0)

    第一种情况,当前节点含有右子树,这种情况下,中序遍历的下一个节点为该节点右子树的最左子节点。因此我们只要从右子节点出发,一直沿着左子节点的指针,就能找到下一个节点。

    第二种情况是,1.当前节点不含有右子树,并且当前节点为父节点的左子节点,这种情况下中序遍历的下一个节点为当前节点的父节点。

    2.当前节点不含有右子树,并且当前节点为父节点的右子节点,这种情况下我们沿着父节点一直向上查找,直到找到一个节点,该节点为父节点的左子节点。这个左子节点的父节点就是中序遍历的下一个节点。

function GetNext(pNode)
{
    // write code here
    if(pNode == null) return null;
    if(pNode.right !== null) { //有右子树 下一个节点就是右子树的 最左边的节点;
        let p = pNode.right;
        while(p.left !== null) {
            p = p.left;
        }
        return p;
    }
    while (pNode.next !== null) { //没有右子树
        if(pNode == pNode.next.left) {
            return pNode.next;
        }
        pNode = pNode. next;
    }
}

发表于 2021-07-04 19:47:00 回复(0)
function GetNext(pNode)
{
    // write code here
    //1.如果一个节点有右子树,那么它的下一个节点就是它的右子树中的最左子节点。也就是说,从右子节点出发一直沿着指向左子节点的指针,我们就能找到下一个节点。

    //2.如果没有右子树,又可以分为两种情况
        //1)如果节点是它父节点的左子节点,那么它的下一个节点就是它的父节点。
        //2)如果一个节点既没有右子树,并且它还是父节点的右子节点,那么需要沿着指向父节点的指针一直向上便利,直到找到一个是它父节点的左子节点的节点。
    if(pNode == null) {
        return null;
    }
    //第一种
    if(pNode.right != null){
        pNode = pNode.right;
        while(pNode.left != null) {
            pNode = pNode.left;
        }
        return pNode;
    }
    //第二种
    while(pNode.next != null) {
        if(pNode == pNode.next.left) {
            return pNode.next;
        }
        pNode = pNode.next;
    }
    return null;
}

发表于 2021-04-05 12:49:47 回复(0)
/*1.如果一个节点有右子树,那么它的下一个节点就是它的右子树中的最左子节点。也就是说,从右子节点出发一直沿着指向左子节点的指针,我们就能找到下一个节点。

2.如果没有右子树,又可以分为两种情况

如果节点是它父节点的左子节点,那么它的下一个节点就是它的父节点。
如果一个节点既没有右子树,并且它还是父节点的右子节点,那么需要沿着指向父节点的指针一直向上遍历,直到找到一个当前节点的父节点的左节点是其本身的节点。
*/
function GetNext(pNode) {
    if (pNode === null) {
        return null;
    }
    if (pNode.right !== null) {
        // 第1种
        pNode = pNode.right;
        while (pNode.left !== null) {
            pNode = pNode.left;
        }
        return pNode;
    }
    while (pNode.next !== null) {
        // 第2种,直到找到一个当前节点的父节点的左节点是其本身的节点。
        if (pNode === pNode.next.left) {
            return pNode.next;
        }
        pNode = pNode.next;
    }
    return null;
}
pNode.next看了半天才明白指向的是当前节点的父节点,不得不说牛客网的题目描述怕是学生能看懂了一样,这题还好,很多题目的输入和输出描述说都不说。还有官方答案解析更是不想吐槽了
发表于 2020-08-20 21:43:59 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    //var p=null;
    if(pNode==null) return pNode;
    if(pNode.right){
        //如果存在右子树
        pNode=pNode.right;//将当前节点转化为原来节点的右子节点,寻找该右子树最左边的节点
        while(pNode.left!=null){
            pNode=pNode.left;
        }
        return pNode
    }
    while(pNode.next!=null){
        //没有右子树,找第一个当前节点是父节点左孩子的节点
        if(pNode==pNode.next.left)
            return pNode.next;
    }
    return null;
    //直到根节点依旧没有找到,返回null
}
代码有问题

发表于 2020-08-20 15:48:50 回复(0)
function GetNext(pNode)
{
    // write code here
    if(!pNode){
        return pNode
    }
    if(pNode.right){
        pNode = pNode.right
        while(pNode.left){
            pNode = pNode.left
        }
        return pNode
    }
    while(pNode.next){
        if(pNode === pNode.next.right){
            pNode = pNode.next
        }else{
            return pNode.next
        }
        
    }
    return null
思路:
1.考虑basecase
2.如果给定的节点有右子节点,就向给定节点的右子树遍历,并且让
pNode = pNode.right
遍历pNode的左子树直到pNode.left为空,则此pNode为所求
3..如果给定的节点(pNode)没有右子节点,就向给定节点的父亲遍历,并判断pNode是否为其父亲的右子节点,若为真,则令
 pNode = pNode.next
直到pNode为其父亲的左子节点,则pNode的父亲为所求。若pNode的父亲为空,则退出循环返回null,就是下图中I节点
发表于 2020-07-09 22:07:41 回复(0)
用了最好理解也是最蠢的办法:先把这个树中序遍历,结果放在数组里面,然后在数组indexOf这个结点,找到之后return下一个结点就OK了。不过要先找到这个树的根结点,就用给的结点的next指针一层层往上找。这里指向父结点的指针命名为next真是槽多无口
function GetNext(pNode)
{
    if (pNode === null) {
        return null
    }
    //找到根结点
    let cur = pNode
    while(cur.next){
        cur = cur.next
    }


    let list = []
    let order = midOrder(cur,list)
    let index = order.indexOf(pNode)
    //要考虑到给的结点可能是最后一个结点的情况
    if(index!=order.length-1){
        return order[index+1]
    }else{
        return null
    }
}

//中序遍历递归函数
function midOrder(node,list){
    if(node != null){
        midOrder(node.left,list)
        list.push(node)
        midOrder(node.right,list)
    }
    return list
}


发表于 2020-03-08 20:09:37 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    // write code here
    if(!pNode) return null;
    if(pNode.right === null){
        let currNode = pNode;
        while(currNode.next){
            if(currNode === currNode.next.left){
                return currNode.next;
            }
            currNode = currNode.next;
        }
        return null;
    }else{
        let currNode = pNode.right;
        while(currNode.left){
            currNode = currNode.left;
        }
        return currNode;
    }
}

发表于 2019-09-18 01:04:27 回复(0)
JS解法:
1、空树;
2、判断该节点是否有右子树,有的话找到其右子树,一直往下找到最深的左子树即为下一个节点;
3、若该节点没有右子树,找到该节点上(包括该节点)第一个 其父节点 的左子树 是其本身的节点(p.next.left == p);
function GetNext(pNode)
{
    if(pNode == null) return null;
    if(pNode.right != null){
        pNode = pNode.right;
        while(pNode.left != null){
            pNode = pNode.left;
        }
        return pNode;
    }
    while(pNode.next != null){
        if(pNode.next.left == pNode) return pNode.next;
        pNode = pNode.next;
    }

}


发表于 2019-08-28 16:15:35 回复(0)
  • 循环next找到根节点
  • 中序遍历存数组
  • 遍历数组
function TreeLinkNode(x){
  this.val = x;
  this.left = null;
  this.right = null;
  this.next = null;
}

let arr = [];
function GetNext(pNode)
{
  // write code here
  // 找到根节点
  let r = pNode;
  while (r.next) {
    r = r.next;
  }
  // 此时r为根节点
  // 中序遍历
  inOrderTraverse(r, pNode);
  // console.log(arr);

  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === pNode) {
      return arr[i+1];
    }
  }

  // return resNode;
}

function inOrderTraverse(root, target) {
  let r = root;

  r.left && inOrderTraverse(r.left, target);
  if (r.val) {
    arr.push(r);
  }
  r.right && inOrderTraverse(r.right, target);
}

let node1 = new TreeLinkNode(1);
let node2 = new TreeLinkNode(2);
let node3 = new TreeLinkNode(3);
let node4 = new TreeLinkNode(4);
let node5 = new TreeLinkNode(5);
// let node6 = new TreeLinkNode(6);

// node1.left = node2;
// node1.right = node4;

// node2.right = node3;
// node2.next = node1;

// node3.next = node2;

// node4.left = node5;
// node4.right = node6;
// node4.next = node1;

// node5.next = node4;

// node6.next = node4;

// let res = GetNext(node3);

node1.left = node2;
node1.right = node5;

node2.left = node3;
node2.right = node4;

node2.next = node1;
node3.next = node2;
node4.next = node2;
node5.nect = node1;

let res = GetNext(node1);

console.log(res);
发表于 2019-08-14 13:56:16 回复(0)
// 判断pNode是否有右子树,pNext为右子树最左的节点 // 如果pNode没有右子树,判断pNode是否有父节点: //     1、当pNode为父节点的左子树,则pNext为父节点, //     2、否则沿着父节点向上一直追溯到一个节点是它的父节点的左节点
function GetNext(pNode) {     // write code here     var pRoot = pNode.next;     if ( pNode == null) {         return null     }     if ( pNode.right != null) {         var pRight = pNode.right;         while ( pRight.left != null ) {             pRight = pRight.left         }         return pRight     }     while ( pRoot ) {         if ( pNode == pRoot.left) {             return pRoot         } else {             pNode = pRoot;             pRoot = pRoot.next         }     }     return null //必须加上,否则编译不通过,当pNode无有节点和父节点时无法判断 }

编辑于 2019-07-21 15:04:15 回复(0)
// 中序遍历的顺序 左 - 根 - 右
// 所以寻找下一个节点的优先级应该反过来 优先级 右 - 根 - 左
// 右节点不为空 - 取右节点的最左侧节点
// 右节点为空 - 如果父节点是父亲节的父节点的左节点 取父节点
// 右节点为空 - 如果父节点是父亲节的父节点的右节点 该节点已经被遍历过,再往上层寻找...
// 左节点一定在当前节点之前被遍历过

    function GetNext(pNode) {
      if (!pNode) {
        return null;
      }
      if (pNode.right) {
        pNode = pNode.right;
        while (pNode.left) {
          pNode = pNode.left;
        }
        return pNode;
      } else {
        while (pNode) {
          if (!pNode.next) {
            return null;
          } else if (pNode == pNode.next.left) {
            return pNode.next;
          }
          pNode = pNode.next;
        }
        return pNode;
      }
    }

发表于 2019-03-29 17:05:11 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    // write code here
    if(pNode == null){return false;}
    if(pNode.right){
        pNode = pNode.right;
        while(pNode.left){
            pNode = pNode.left;
        }
        return pNode;
    }
    while(pNode.next){ //判断是不是根结点
        if(pNode == pNode.next.left){
            return pNode.next;
        }else{  //如果是右子数 则返回root
            pNode = pNode.next;
        }
    }
   
  }
发表于 2018-09-07 11:21:48 回复(0)
function GetNext(pNode)
{
    // write code here
    var node = pNode;
    if(!node){
        return null;
    }
    if(node.next === null){
        //根节点
        if(node.right){
            var temptNode = node.right;
            while(temptNode.left){
                temptNode = temptNode.left;
            }
            return temptNode;
        }else{
            return null;
        }
    }else if(node.next !== null &&(node.left !== null||node.right !== null)){
        //中间层节点
        if(node.right){
            var temptNode = node.right;
            while(temptNode.left){
                temptNode = temptNode.left;
            }
            return temptNode;
        }else{
            return node.next;
        }
    }else if(node.next !== null && node.left === null && node.right === null){
        //叶子节点
       
        while(node.next !== null){
            var parent = node.next;
            if(parent.left === node){
                //左节点
                return parent;
            }else{
                node = node.next
            }
        }
        
        return null;
    }
发表于 2018-05-13 15:59:47 回复(0)
function GetNext(pNode)
{
    if(!pNode){return null;}    // 空指针
    var p = null;
    if(pNode.right){            // 存在右子树
        p = pNode.right;
        while(p.left){
            p = p.left;
        }
    }else{                      // 不存在右子树
        p = pNode.next;
        if(pNode.next && pNode.next.right == pNode){
            while(p.next && p.next.right == p){    // 上找所有自己是父的右子的节点
                p = p.next;
            }
            if(p.next == null){    //没有父节点了
                p =  null;
            }else{
                p = p.next;
            }
        }
    }
    return p;
}

发表于 2018-04-21 14:21:48 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    if(pNode == null){
        return null;
    }
    
    if(pNode.right!=null){
        var pRight = pNode.right;
        while(pRight.left!=null){
            pRight = pRight.left;
        }
        var pNext = pRight;
    }else if(pNode.next!=null){
        var pCurrent = pNode;
        var pParent = pNode.next;
        while(pParent!=null&&pCurrent==pParent.right){
            pCurrent = pParent;
            pParent = pParent.next;
        }
        pNext = pParent;
    }
    return pNext;
}

发表于 2018-03-27 17:33:27 回复(0)
/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;//父节点
}

思路:
if(它有右子树){找该右子树的左叶子}
else{//它没有右子树
    if(处于父节点的左子树){下一个节点是父节点}
    else if(处于父节点的右子树){
        if(找到一个处于左子树的祖先节点){则下一个节点就是这个祖先节点}
        esle if(没有处于左子树中的祖先节点){没有下一个节点}
    }
}

*/
function GetNext(pNode)
{
    if(!pNode){
        return null;
    }
    var target=null;
    if(pNode.right){ //存在右子树
        target=pNode.right;
        while(target.left){
            target=target.left;
        }
    }else{//不存在右子树
            var parent=pNode.next;
            var curNode=pNode;
            while(parent!=null && curNode == parent.right){ //父节点不是祖父节点的左节点的话就继续找
                curNode=parent;
                parent=parent.next;
            }
            target=parent;
    }
    return target;
}

发表于 2018-03-10 15:01:56 回复(0)