携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
一、题目
LeetCode 二叉搜索树中的中序后继
给定一棵二叉搜索树和其中的一个节点 p ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null 。
节点 p 的后继是值比 p.val 大的节点中键值最小的节点,即按中序遍历的顺序节点 p 的下一个节点。
示例 1:
输入:root = [2,1,3], p = 1
输出:2
解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。
示例 2:
输入:root = [5,3,6,2,4,null,null,1], p = 6
输出:null
解释:因为给出的节点没有中序后继,所以答案就返回 null 了。
提示:
树中节点的数目在范围 [1, 104] 内。
-105 <= Node.val <= 105
树中各节点的值均保证唯一。
二、题解
给定有一颗二叉搜索树,二叉搜索树就是如果左子树不为空的话,那么左子树上所有节点值都小于根节点值;如果右子树不为空的话,那么右子树的所有节点值都大于根节点值。要找到某个指定节点的中序遍历后续节点。
方法一
可以直接按题目要求先对二叉搜索树进行中序遍历,在中序遍历之后获取的遍历结果找到指定的节点p,如果节点p之后还有后续节点就返回这个后续节点,否则返回null。具体的通过dfs深度优先搜索遍历给定的二叉搜索树节点,按中序遍历的顺序将节点加入结果数组中,遍历结果数组寻找目标节点p,如果目标节点p不是最后一个节点,那么就返回节点p的后一个节点即可。
方法二
可以利用二叉搜索树的特性,即节点值的大小顺序,遍历二叉搜索树的节点,如果当前节点值大于目标节点p的值,而节点p的中序后继节点是大于节点p的,所以这个节点p的中序后继节点就可能是在左子树中,则需要到左子树中寻找,并且先保存好这个比目标节点p大的当前节点,当遍历结束时这个节点就是节点p的中序后继节点;如果当前节点值小于目标节点p的值,那么就需要到右子树中继续寻找,直到最后遍历结束。
三、代码
方法一 Java代码
class Solution {
List<TreeNode> list = new ArrayList<>();
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
dfs(root);
int idx = list.indexOf(p);
if (idx == list.size() - 1) {
return null;
}
return list.get(idx + 1);
}
private void dfs(TreeNode root) {
if (root == null) {
return;
}
dfs(root.left);
list.add(root);
dfs(root.right);
}
}
时间复杂度:O(n),需要遍历一次二叉树节点。
空间复杂度:O(n),存储遍历结果的数组以及递归消耗栈空间。
方法二 Java代码
class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
TreeNode node = null;
while (root != null) {
if (root.val > p.val) {
node = root;
root = root.left;
} else {
root = root.right;
}
}
return node;
}
}
时间复杂度:O(n),需要遍历下二叉树节点。
空间复杂度:O(1),只需使用常数的空间。