题目链接

LeetCode 面试题 04.06. 后继者[1]

题目描述

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

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

示例1

        输入:
root = [2,1,3], p = 12/ \
1   3
输出:
2

示例2

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

题解

BST+递归

首先本题中的二叉树还是个二叉搜索树,也就是中序遍历是单调递增的,所以我们可以利用这个性质来简化查找过程。

  • 如果结点 p 的值大于等于 root 的值,说明 p 的后继结点在 root 右子树中,那么就递归到右子树中查找。
  • 如果结点 p 的值小于 root 的值,说明 proot 左子树中,而它的后继结点有两种可能,要么也在左子树中,要么就是 root
    • 如果左子树中找到了后继结点,那就直接返回答案。
    • 如果左子树中没有找到后继结点,那就说明 p 的右儿子为空,那么 root 就是它的后继结点。

BST+非递归

  • 如果 p 有右儿子,那么它的后继结点就是右子树的最左边的儿子。
  • 如果 p 没有右儿子,那么它的后继结点就是,沿着 p 往上到 root 的路径中,第一个左儿子在路径上的结点。因为这个结点的左子树中 p 是最右边的结点,是最大的,所以它就是 p 的后继结点。因为是二叉搜索树,我们就可以从根结点开始往 p 走,根据结点值的大小决定走的方向。

一般树+递归

那如果是一般的二叉树,中序遍历就不满足单调递增了,这时候我们就只能找出中序遍历的结点顺序,然后才能得到 p 的后继结点。

所以我们直接采用递归来做中序遍历就行了,中序遍历结果保存下来,最后取 p 的下一个结点。

一般树+非递归

当然还可以采用栈来做中序遍历,这样就是非递归了。同样结果保存下来,最后取 p 的下一个结点。

一般树+Morris遍历

如果看过我前两天的一道关于二叉搜索树的题解:
韦阳的博客:【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事![2]

知乎专栏:【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事![3]

那么你一定会知道这个 Morris 遍历算法,用常数空间来解决结点无法访问父结点的问题。这里就不细讲了,请直接看之前的题解。方法是一样的,用 Morris 遍历得到中序遍历,然后遍历一遍找到 p ,输出它的下一个结点就行了。

代码

BST+递归(c++)

        class Solution {public:TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {if (root == NULL || p == NULL) return NULL;if (p->val >= root->val) {return inorderSuccessor(root->right, p);} else {TreeNode* left = inorderSuccessor(root->left, p);return left ? left : root;}}
};

BST+非递归(c++)

        class Solution {public:TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {if (p->right) {p = p->right;while (p->left) p = p->left;return p;}TreeNode* res = NULL;while (root != p) {if (root->val < p->val) {root = root->right;} else {res = root;root = root->left;}}return res;}
};

一般树+递归(c++)

        class Solution {public:void inorder(TreeNode* root, vector<TreeNode*>& res) {if (root->left) inorder(root->left, res);res.push_back(root);if (root->right) inorder(root->right, res);}TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {vector<TreeNode*> res;inorder(root, res);res.push_back(NULL);for (int i = 0; i < res.size(); ++i) {if (res[i] == p) {return res[i+1];}}return NULL;}
};

一般树+非递归(c++)

        class Solution {public:TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {vector<TreeNode*> res;stack<TreeNode*> st;while (!st.empty() || root) {while (root) {st.push(root);root = root->left;}root = st.top();st.pop();res.push_back(root);root = root->right;}res.push_back(NULL);for (int i = 0; i < res.size(); ++i) {if (res[i] == p) {return res[i+1];}}return NULL;}
};

一般树+Morris遍历(c++)

        class Solution {public:TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {vector<TreeNode*> res;TreeNode *rightmost = NULL;while (root) {if (root->left) {rightmost = root->left;while (rightmost->right && rightmost->right != root) {rightmost = rightmost->right;}if (rightmost->right != root) {rightmost->right = root;root = root->left;} else {res.push_back(root);rightmost->right = NULL;root = root->right;}} else {res.push_back(root);root = root->right;}}res.push_back(NULL);for (int i = 0; i < res.size(); ++i) {if (res[i] == p) {return res[i+1];}}return NULL;}
};

参考资料

[1]

LeetCode 面试题 04.06. 后继者: https://leetcode-cn.com/problems/successor-lcci/

[2]

【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事!: https://godweiyang.com/2020/03/18/leetcode-99/

[3]

【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事!: https://zhuanlan.zhihu.com/p/114143194

【每日算法Day 76】经典面试题:中序遍历的下一个元素,5大解法汇总!相关推荐

  1. 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 8 二叉树中序遍历的下一个结点 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注 ...

  2. 二叉树中序遍历的下一个节点

    题目描述: 给定一棵二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?树中的节点除了有两个分别指向左.右子节点的指针,还有一个指向父节点的指针. 解题思路: 这道题意即:给定一个节点,按照中序 ...

  3. 【二叉树】剑指offer:二叉树中序遍历的下一个节点

    思路一:vector存放中序遍历,然后查找输出 注意: pNode是待查找节点,因为要通过父节点遍历二叉树,所以首先要找到父节点 TreeNode *temp=t; TreeNode *root; w ...

  4. 新手学习算法----二叉树(将一个二叉查找树按照中序遍历转换成双向链表)

    题目:将一个二叉查找树按照中序遍历转换成双向链表. 给定一个二叉查找树: 4/ \2 5/ \ 1 3 返回 1<->2<->3<->4<->5. 思路 ...

  5. 【图解二叉树】如何用中序遍历一棵二叉树?(三种解法)

    目录 题解 递归实现 迭代实现 莫里斯遍历 题解 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1\2/3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过 ...

  6. leetcode 105. 从前序与中序遍历序列构造二叉树 c语言递归解法

    如题: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素.例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3 ...

  7. LeetCode 105 Construct Binary Tree from Preorder and Inorder Traversal-前序中序遍历构造二叉树-Python和Java递归解法

    题目地址:Construct Binary Tree from Preorder and Inorder Traversal - LeetCode Given preorder and inorder ...

  8. Morris遍历算法 树的中序遍历

    Morris遍历算法 树的中序遍历 树的中序遍历 一.普通方法 1.递归实现 2.栈实现 二.Morris遍历 1.算法 2.代码 总结 树的中序遍历 对于当前结点,先输出它的左孩子,然后输出该结点, ...

  9. 二叉排序树的中序遍历规律_看懂这篇文章,玩转二叉查找树

    所谓二叉查找树,就是按照二分进行查找,每次查询只需要选择其中一个子树就进行查找,从而减少查找次数,提升查询效率! 一.介绍 在前面的文章中,我们对树这种数据结构做了一些基本介绍,今天我们继续来聊聊一种 ...

  10. LeetCode 94. Binary Tree Inorder Traversal--二叉树中序遍历--递归,迭代--C++,Python解法

    题目地址:Binary Tree Inorder Traversal - LeetCode Given a binary tree, return the inorder traversal of i ...

最新文章

  1. float向u8和s8的转换
  2. redis启动后 允许访问_最全Redis基本知识
  3. python注册登录系统_Python实现简单用户注册信息管理系统
  4. ES7和ES8的了解
  5. AndroidOkhttp3上传单个文件
  6. windows下vagrant的安装使用
  7. visual studio编译linux,在 Visual Studio 中配置 Linux MSBuild C++ 项目
  8. 7.3(java学习笔记)网络编程之UDP
  9. 查询结果做缓存的例子
  10. nfine框架连接oracle,nfine(nfine快速开发框架)
  11. 计算机组装与维修要学哪些,计算机组装与维修教学基本要求
  12. 我的2020年终回顾:人生,海海,破浪前行
  13. 电脑pin码忘了登录不进系统_做好这些优化,电脑5秒开机不是梦
  14. android apktool使用教程,Apktool 使用教程
  15. hibernate Criteria setProjection
  16. 有限差分法在最优化问题中的应用
  17. 使用ansible统一管理修改Linux和Windows管理员密码
  18. is running 8724480B beyond the ‘PHYSICAL‘ memory limit.
  19. 实现字典树(前缀树、Trie树)并详解其应用
  20. MSP430控制AD7712采集数据

热门文章

  1. 获取元素到页面上的位置
  2. ASP.NET MVC3书店--第二节 控制器(转)
  3. STM32(十一)- 串行FLASH文件系统FatFs
  4. WPF管理系统自定义分页控件 - WPF特工队内部资料
  5. easyui弹出加载遮罩层(转)
  6. 贝叶斯推断之最大后验概率(MAP)
  7. 将对象序列化和反序列化
  8. 主机字节序和网络字节序(大端序,小端序,网络序)
  9. 《BI那点儿事》Microsoft 决策树算法
  10. IE9 表格错位bug