剑指offer--二叉树的下一个节点。

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

输入描述:

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

返回值描述:

返回传入的子树根节点的下一个节点,后台会打印输出这个节点

示例:

输入:{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

题目解读:该题任给一个节点,让输出这棵树在经过中序遍历后,给出节点所在位置的下一个节点。

解题方法:

1.暴力破题

方法描述:题中给出了父节点的指针next,我们可以根据这个找到根节点,再进行中序遍历得到一个数组,再把所给节点带入数组,得出当前所在位置,并返回下一个节点;

代码:

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
import java.util.*;
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        Stack<TreeLinkNode> a=new Stack<>();
        ArrayList<TreeLinkNode> ans=new ArrayList<>();
        TreeLinkNode f=pNode;
        while(f.next!=null) //找出根结点;
        {
            f=f.next; 
        
        }
            
        a.push(f);
        TreeLinkNode b=f;
        if(f.left==null&&f.right==null) //当所给节点为根节点且左右节点都为空时返回null
            return null;
        while(a.size()!=0) //中序遍历
        {
            
            if(b!=null)
            {
                a.push(b);
                b=b.left;
            }
            else
            {
                b=a.pop();
                ans.add(b);
                
                    b=b.right;
                
            }
        }
        int i=1;
        for(TreeLinkNode s:ans)
        {
            if(s==pNode)
                break;
            i++;
        }
        if(i+1>=ans.size()) //i+1是因为size()函数求出长度比数组储存长度大1(应该是);
            return null;
            else
        return ans.get(i);
    }
}

 这种方法便于理解,只有一个中序遍历在里面,但面试不适合;

方法二:利用中序遍历的性质

 方法描述:对于二叉树中序遍历,按照左中右的顺序进行遍历,情况1:所以当给定结点有右节点时,我们的目标节点一定会与之相关,以上图为例,假定所给节点为根节点,其结点为C,但c不是中序遍历后符合题意的结点,因为c的左节点f会在c的前面遍历,显然若f有左节点时也会在f前面遍历,所以这种情况就是当右孩子有左节点时,返回右孩子的最左结点。当右孩子没有左节点时就是返回右孩子。

情况2:当给定结点无右孩子时,当它是父节点的左孩子时,例如h结点无右孩子且它为父节点的左孩子,显然中序遍历后h结点的下一个结点就是其父节点e。

同样无右节点,但它为父节点右节点时,例如i,显然它的父亲已经再之前就存进数组了,这时就要在祖辈中找一个右父节点(例如a),这个时a结点就是要找的结点。

情况2总结一下就是要在父辈中找一个右父节点(即父节点的左节点是否与当前结点相等,若相等返回父节点,若遍历到父节点为空都没找到返回null)

代码:

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
import java.util.*;
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        Stack<TreeLinkNode> a=new Stack<>();
        ArrayList<TreeLinkNode> ans=new ArrayList<>();
        TreeLinkNode ans1=pNode.right;
        TreeLinkNode ans2=pNode;
        if(ans1!=null)//情况1
        {
            while(ans1.left!=null)
            {
                ans1=ans1.left;
                //return ans1.left;
            }
            return ans1;
        }
       
            while(ans2.next!=null) //情况2
            {
                 if(ans2==ans2.next.left)
                {
                     return ans2.next;
                }
                    ans2=ans2.next;
            }
               
                   
        return null;
          
    }
}

水平有限,若有错误还请各位大佬指正

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值