题目

设计一个算法,找出二叉搜索树中指定节点的“下一个”节点(也即中序后继)。

如果指定节点没有对应的“下一个”节点,则返回null。

示例 1:

输入: root = [2,1,3], p = 1

2
/
1 3

输出: 2

示例 2: 5 / \ 3 6 / \ 2 4 /
1 输入: root = [5,3,6,2,4,null,null,1], p = 6

输出: null

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/successor-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

思路写在注释里了。

代码

递归 O(n)空间

  1. class Solution {
  2. public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
  3. if (root == null) {
  4. return null;
  5. }
  6. // 如果当前值不大于p的值,说明要找的节点一定在右子树
  7. if (root.val <= p.val) {
  8. return inorderSuccessor(root.right, p);
  9. }
  10. // 接下来判断是否可能是根节点
  11. // 先在左子树中找
  12. TreeNode left = inorderSuccessor(root.left, p);
  13. // 如果没找到返回根节点
  14. if (left == null) {
  15. return root;
  16. }
  17. // 找到了,返回在左子树中找到的节点
  18. return left;
  19. }
  20. }

迭代 O(n)空间

常规迭代的中序遍历,没有利用二叉搜索树的性质。记录好上一个节点和p作比较即可。不推荐

  1. class Solution {
  2. public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
  3. Deque<TreeNode> stack = new ArrayDeque<>();
  4. TreeNode pp = root;
  5. TreeNode pre = null;
  6. while (pp != null || !stack.isEmpty()) {
  7. if (pp != null) {
  8. stack.push(pp);
  9. pp = pp.left;
  10. } else {
  11. TreeNode cur = stack.poll();
  12. if (pre == p) {
  13. return cur;
  14. }
  15. pre = cur;
  16. pp = cur.right;
  17. }
  18. }
  19. return null;
  20. }
  21. }

迭代 O(1)空间

学习一下:利用二叉搜索树的性质后,O(n)空间可以省略。可以看做是树上的二分。

  1. class Solution {
  2. public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
  3. TreeNode cur = root;
  4. TreeNode ans = null;
  5. while (cur != null) {
  6. // 同递归写法中逻辑,如果当前值不大于p的值,说明要找的节点一定在右子树
  7. if (cur.val <= p.val) {
  8. cur = cur.right;
  9. } else {
  10. // 不在右子树,那么可能是根节点,先暂时将ans置为根节点,然后到左子树看
  11. ans = cur;
  12. cur = cur.left;
  13. }
  14. }
  15. return ans;
  16. }
  17. }