[LeetCode] Inorder Successor in BST II 二叉搜索树中的中序后继节点之二
Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
The successor of a node p
is the node with the smallest key greater than p.val
.
You will have direct access to the node but not to the root of the tree. Each node will have a reference to its parent node.
Example 1:
Input:
root = {"$id":"1","left":{"$id":"2","left":null,"parent":{"$ref":"1"},"right":null,"val":1},"parent":null,"right":{"$id":"3","left":null,"parent":{"$ref":"1"},"right":null,"val":3},"val":2}
p = 1
Output: 2
Explanation: 1's in-order successor node is 2. Note that both p and the return value is of Node type.
Example 2:
Input:
root = {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":{"$id":"4","left":null,"parent":{"$ref":"3"},"right":null,"val":1},"parent":{"$ref":"2"},"right":null,"val":2},"parent":{"$ref":"1"},"right":{"$id":"5","left":null,"parent":{"$ref":"2"},"right":null,"val":4},"val":3},"parent":null,"right":{"$id":"6","left":null,"parent":{"$ref":"1"},"right":null,"val":6},"val":5}
p = 6
Output: null
Explanation: There is no in-order successor of the current node, so the answer isnull
.
Example 3:
Input:
root = {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":{"$id":"4","left":null,"parent":{"$ref":"3"},"right":null,"val":2},"parent":{"$ref":"2"},"right":{"$id":"5","left":null,"parent":{"$ref":"3"},"right":null,"val":4},"val":3},"parent":{"$ref":"1"},"right":{"$id":"6","left":null,"parent":{"$ref":"2"},"right":{"$id":"7","left":{"$id":"8","left":null,"parent":{"$ref":"7"},"right":null,"val":9},"parent":{"$ref":"6"},"right":null,"val":13},"val":7},"val":6},"parent":null,"right":{"$id":"9","left":{"$id":"10","left":null,"parent":{"$ref":"9"},"right":null,"val":17},"parent":{"$ref":"1"},"right":{"$id":"11","left":null,"parent":{"$ref":"9"},"right":null,"val":20},"val":18},"val":15}
p = 15
Output: 17
Example 4:
Input:
root = {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":{"$id":"4","left":null,"parent":{"$ref":"3"},"right":null,"val":2},"parent":{"$ref":"2"},"right":{"$id":"5","left":null,"parent":{"$ref":"3"},"right":null,"val":4},"val":3},"parent":{"$ref":"1"},"right":{"$id":"6","left":null,"parent":{"$ref":"2"},"right":{"$id":"7","left":{"$id":"8","left":null,"parent":{"$ref":"7"},"right":null,"val":9},"parent":{"$ref":"6"},"right":null,"val":13},"val":7},"val":6},"parent":null,"right":{"$id":"9","left":{"$id":"10","left":null,"parent":{"$ref":"9"},"right":null,"val":17},"parent":{"$ref":"1"},"right":{"$id":"11","left":null,"parent":{"$ref":"9"},"right":null,"val":20},"val":18},"val":15}
p = 13
Output: 15
Note:
- If the given node has no in-order successor in the tree, return
null
. - It's guaranteed that the values of the tree are unique.
- Remember that we are using the
Node
type instead ofTreeNode
type so their string representation are different.
Follow up:
Could you solve it without looking up any of the node's values?
这道题是之前的那道 Inorder Successor in BST 的后续,之前那道题给了我们树的根结点,而这道题并没有确定给我们根结点,只是给了树的任意一个结点,然后让求给定结点的中序后继结点。这道题比较好的一点就是例子给的比较详尽,基本覆盖到了大部分的情况,包括一些很 tricky 的情况。首先来看例子1,结点1的中序后继结点是2,因为中序遍历的顺序是左-根-右。还是例子1,结点2的中序后续结点是3,这样我们就知道中序后续结点可以是其父结点或者右子结点。再看例子2,结点6的中序后续结点是空,因为其已经是中序遍历的最后一个结点了,所以没有后续结点。例子3比较 tricky,结点 15 的中序后续结点不是其右子结点,而是其右子结点的左子结点 17,这样才符合左-根-右的顺序。例子4同样 tricky,结点 13 的中序后继结点并不是其亲生父结点,而是其祖爷爷结点 15。
好,看完了这四个例子,我们应该心里有些数了吧。后继结点出现的位置大致可以分为两类,一类是在子孙结点中,另一类是在祖先结点中。仔细观察例子不难发现,当某个结点存在右子结点时,其中序后继结点就在子孙结点中,反之则在祖先结点中。这样我们就可以分别来处理,当右子结点存在时,我们需要找到右子结点的最左子结点,这个不难,就用个 while 循环就行了。当右子结点不存在,我们就要找到第一个比其值大的祖先结点,也是用个 while 循环去找即可,参见代码如下:
解法一:
class Solution {
public:
Node* inorderSuccessor(Node* node) {
if (!node) return nullptr;
Node *res = nullptr;
if (node->right) {
res = node->right;
while (res && res->left) res = res->left;
} else {
res = node->parent;
while (res && res->val < node->val) res = res->parent;
}
return res;
}
};
本题的 Follow up 让我们不要访问结点值,那么上面的解法就不行了。因为当 node 没有右子结点时,我们没法通过比较结点值来找到第一个大于 node 的祖先结点。虽然不能比较结点值了,我们还是可以通过 node 相对于其 parent 的位置来判断,当 node 是其 parent 的左子结点时,我们知道此时 parent 的结点值一定大于 node,因为这是二叉搜索树的性质。若 node 是其 parent 的右子结点时,则将 node 赋值为其 parent,继续向上找,直到其 parent 结点不存在了,此时说明不存在大于 node 值的祖先结点,这说明 node 是 BST 的最后一个结点了,没有后继结点,直接返回 nullptr 即可,参见代码如下:
解法二:
class Solution {
public:
Node* inorderSuccessor(Node* node) {
if (!node) return nullptr;
if (node->right) {
node = node->right;
while (node && node->left) node = node->left;
return node;
}
while (node) {
if (!node->parent) return nullptr;
if (node == node->parent->left) return node->parent;
node = node->parent;
}
return node;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/510
类似题目:
参考资料:
https://leetcode.com/problems/inorder-successor-in-bst-ii/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Inorder Successor in BST II 二叉搜索树中的中序后继节点之二的更多相关文章
- [LeetCode] Inorder Successor in BST 二叉搜索树中的中序后继节点
Given a binary search tree and a node in it, find the in-order successor of that node in the BST. No ...
- [LeetCode] 285. Inorder Successor in BST 二叉搜索树中的中序后继节点
Given a binary search tree and a node in it, find the in-order successor of that node in the BST. Th ...
- [Swift]LeetCode285. 二叉搜索树中的中序后继节点 $ Inorder Successor in BST
Given a binary search tree and a node in it, find the in-order successor of that node in the BST. Th ...
- 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用
一般来说,删除节点可分为两个步骤: 首先找到需要删除的节点: 如果找到了,删除它. 说明: 要求算法时间复杂度为 O(h),h 为树的高度. 示例: root = [5,3,6,2,4,null,7] ...
- [Swift]LeetCode450. 删除二叉搜索树中的节点 | Delete Node in a BST
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...
- Java实现 LeetCode 450 删除二叉搜索树中的节点
450. 删除二叉搜索树中的节点 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变.返回二叉搜索树(有可能被更新)的根节点的引 ...
- 刷题-力扣-230. 二叉搜索树中第K小的元素
230. 二叉搜索树中第K小的元素 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a ...
- LeetCode Inorder Successor in BST
原题链接在这里:https://leetcode.com/problems/inorder-successor-in-bst/ Given a binary search tree and a nod ...
- [LeetCode] Delete Node in a BST 删除二叉搜索树中的节点
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...
随机推荐
- SQL server 数据库中插入中文变???格式乱码的问题另一种容易忽略的情况(C#操作dapper)
1.先查查 VS2015 中的XXX.cs页面中编码格式,记事本打开另存一下,编码格式可能是ANSI改为unioncode. (中文前面加N或者改排序规则解决不了的情况有可能是以上原因.)
- 团队Github实战训练
班级:软件工程1916|W 作业:团队Github实战训练 团队名称:SkyReach Github地址:Github地址 贡献比例表 队员学号 队员姓名 此次活动任务 贡献比例 221600106 ...
- linux的cron
linux系统由cron(crond)这个系统服务来控制的,linux系统上原来有非常多的计划性工作,因此,这个系统服务是默认启动的.cron进程每分钟会定期检查是否有要执行的任务,如果有就自动执行该 ...
- 处理H5新标签方法
语义化 HTML5中加入了更加具有语义化的标签,比如header,nav,footer等,可以为搜索引擎优化,让爬虫能更好地理解网页结构. 但是对于新标签的兼容性不是很好,IE9以下旧版本不支持新的语 ...
- 【JS】Javascript数组操作
1.提取数组中每个对象的某个属性组成新的数组 如数组为: let arry = [ { name: 'zhao', 'age': 18 }, { name: 'qian', 'age': 19 }, ...
- Django 之 路由URL,视图,模板,ORM操作
1.后台管理的左侧菜单,默认只有第一个页签下面的选项是显示的,点了别的页签再显示别的页签下面的选项,问题是:点了任何菜单的选项后,左侧菜单又成了第一个页签的选项显示,别的页签隐藏,也就是左侧的菜单刷新 ...
- Django组件-cookie与session
一.会话跟踪技术 1.什么是会话跟踪技术 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而 ...
- 马拉车算法——边界拓展时加限制hdu4513
#include<bits/stdc++.h> using namespace std; #define maxn 500005 int n,p[maxn],s[maxn],s_new[m ...
- 奇葩最小生成树--->走廊泼水节(tyvj1391)
题目描述 话说,中中带领的OIER们打算举行一次冬季泼水节,当然这是要秘密进行的,绝对不可以让中中知道.不过中中可是老江湖了,当然很快就发现了我们的小阴谋,于是他准备好水枪迫不及待的想要加入我们了. ...
- 编译问题解决:LINK : fatal error LNK1104: 无法打开文件“*.dll”
一.引言 编译项目的时候,总会遇到些奇怪的问题,比如说以下这种: LINK : fatal error LNK1104: 无法打开文件“..\bin\ICPRegistration.dll” 我在编译 ...