【每日算法Day 76】经典面试题:中序遍历的下一个元素,5大解法汇总!
题目链接
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
的值,说明p
在root
左子树中,而它的后继结点有两种可能,要么也在左子树中,要么就是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大解法汇总!相关推荐
- 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 8 二叉树中序遍历的下一个结点 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注 ...
- 二叉树中序遍历的下一个节点
题目描述: 给定一棵二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?树中的节点除了有两个分别指向左.右子节点的指针,还有一个指向父节点的指针. 解题思路: 这道题意即:给定一个节点,按照中序 ...
- 【二叉树】剑指offer:二叉树中序遍历的下一个节点
思路一:vector存放中序遍历,然后查找输出 注意: pNode是待查找节点,因为要通过父节点遍历二叉树,所以首先要找到父节点 TreeNode *temp=t; TreeNode *root; w ...
- 新手学习算法----二叉树(将一个二叉查找树按照中序遍历转换成双向链表)
题目:将一个二叉查找树按照中序遍历转换成双向链表. 给定一个二叉查找树: 4/ \2 5/ \ 1 3 返回 1<->2<->3<->4<->5. 思路 ...
- 【图解二叉树】如何用中序遍历一棵二叉树?(三种解法)
目录 题解 递归实现 迭代实现 莫里斯遍历 题解 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1\2/3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过 ...
- leetcode 105. 从前序与中序遍历序列构造二叉树 c语言递归解法
如题: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素.例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3 ...
- 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 ...
- Morris遍历算法 树的中序遍历
Morris遍历算法 树的中序遍历 树的中序遍历 一.普通方法 1.递归实现 2.栈实现 二.Morris遍历 1.算法 2.代码 总结 树的中序遍历 对于当前结点,先输出它的左孩子,然后输出该结点, ...
- 二叉排序树的中序遍历规律_看懂这篇文章,玩转二叉查找树
所谓二叉查找树,就是按照二分进行查找,每次查询只需要选择其中一个子树就进行查找,从而减少查找次数,提升查询效率! 一.介绍 在前面的文章中,我们对树这种数据结构做了一些基本介绍,今天我们继续来聊聊一种 ...
- LeetCode 94. Binary Tree Inorder Traversal--二叉树中序遍历--递归,迭代--C++,Python解法
题目地址:Binary Tree Inorder Traversal - LeetCode Given a binary tree, return the inorder traversal of i ...
最新文章
- float向u8和s8的转换
- redis启动后 允许访问_最全Redis基本知识
- python注册登录系统_Python实现简单用户注册信息管理系统
- ES7和ES8的了解
- AndroidOkhttp3上传单个文件
- windows下vagrant的安装使用
- visual studio编译linux,在 Visual Studio 中配置 Linux MSBuild C++ 项目
- 7.3(java学习笔记)网络编程之UDP
- 查询结果做缓存的例子
- nfine框架连接oracle,nfine(nfine快速开发框架)
- 计算机组装与维修要学哪些,计算机组装与维修教学基本要求
- 我的2020年终回顾:人生,海海,破浪前行
- 电脑pin码忘了登录不进系统_做好这些优化,电脑5秒开机不是梦
- android apktool使用教程,Apktool 使用教程
- hibernate Criteria setProjection
- 有限差分法在最优化问题中的应用
- 使用ansible统一管理修改Linux和Windows管理员密码
- is running 8724480B beyond the ‘PHYSICAL‘ memory limit.
- 实现字典树(前缀树、Trie树)并详解其应用
- MSP430控制AD7712采集数据