【leetcode】二叉搜索树中的中序后继

一、题目描述

给定一棵二叉搜索树和其中的一个节点 p ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null 。

节点 p 的后继是值比 p.val 大的节点中键值最小的节点,即按中序遍历的顺序节点 p 的下一个节点。

在这里插入图片描述

输入:root = [2,1,3], p = 1
输出:2
解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。

二、代码思路

中序遍历,在中序遍历的时候维护两个节点,一个是当前访问的节点,一个是当前访问节点的上一个节点。

如果上一个prev节点iu是目标节点,那么当前节点就是目标节点的中序遍历后继。

最好使用,非递归的中序遍历,这样找到prev之后,很容易返回。递归形式的中序遍历,不好记录上一个节点和下一个节点。

三、代码题解

非递归形式中序遍历:

public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
        TreeNode prev = null, curr = root;
        while (!stack.isEmpty() || curr != null) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            if (prev == p) {
                return curr;
            }
            prev = curr;
            curr = curr.right;
        }
        return null;
    }
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode curNode;
    private TreeNode preNode;
    private TreeNode target;
    private TreeNode res; 
    private TreeNode firstNode;
    private int flag = 0;
    private void dfs(TreeNode node, TreeNode preNode) {
        if (node == null) return;
        dfs(node.left, preNode);
        curNode = node;
        if (preNode == target) {
            res = curNode;
        } else {
            preNode = node;
        }
        dfs(node.right,curNode);
    }
    //获取树的最左节点
    private TreeNode getFirstNode(TreeNode root) {
        while (true) {
            if (root.left != null) {
                root = root.left;
                continue;
            }
            if (root.right != null) {
                root = root.right;
                continue;
            }
            if (root.left == null && root.right == null) {
                return root;
            }
        }
    }
    private TreeNode getFirstNode1(TreeNode node) {
        TreeNode left = null;
        TreeNode right = null;
        if (node == null) return null;
        if (node.left != null) {
            left = getFirstNode(node.left);
        } else if (node.right != null) {
            right = getFirstNode(node.right);
        }
        if (left == null && right == null && flag == 0) {
            flag = 1;
            firstNode = node;
            return node;
        }
        return null;
    }
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        //二叉搜索树:类似于二分,能够优化排序。
        //在二叉搜索树中某个节点的后继:可以理解为该节点中序遍历之后的下一个节点,而且这节点是大于该节点中最小的节点。
        //所以我们可以采用 双指针 + 中序遍历的手段,双指针分别标记当前节点和下一个节点。
        this.target = p;
        getFirstNode(root);
        dfs(root, firstNode);
        return res;
    }
}

C语言版递归找下一个节点:

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

class Successor {
public:
    //中序遍历函数
    void ldr_erach(TreeNode *root, int p, int &post, int &val)
    {
        if (root == NULL) return ;
        ldr_erach(root->left, p, post,val);          //根据中序遍历的顺序,只要p匹配上那么下一个就是我们要找的值
         if (1 == post)                                  //直接用val的引用接收,post作为标志位也要用引用去改变
         {                                             //找到了就把post改成1,接收完后改成-1这样两个条件就不会触发
             val = root->val;
             post = -1;
         }
        else if (0 == post && p == root->val)
        {
           post=1; 
        }
        ldr_erach(root->right,  p, post, val);
    }
    int findSucc(TreeNode* root, int p) {
        // write code here
        int val = 0,post = 0;
        ldr_erach(root,  p,  post, val);
        return val;
    }
};

java版递归找后继:

package leetcode;

/*
 * @author lzy
 * @version 1.0
 * */
public class treeFindNext {
    public static void main(String[] args) {
        TreeNode root = new TreeNode(2);
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(3);
        root.left = node1;
        root.right = node2;
        inorderSuccessor(root,node1);
    }
    private static TreeNode res;
    public static void dfs(TreeNode node, int post, TreeNode p) {
        if (node == null) return;
        dfs(node.left, post, p);
        if (post == 1) {
            res = node;
            post = -1;
        } else if (post == 0 && node == p) {
            post = 1;
        }
        dfs(node.right, post, p);
    }
    public static TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        dfs(root, 0, p);
        return res;
    }
}
class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }

由于Java中只有值传递这样的概念,所以其实上一层post修改之后,不会影响到下一层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值