剑指OFFER_二叉树的下一个节点
剑指OFFER_二叉树的下一个节点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路
拿到这道题一开始我的思路是写一个中序遍历,带入这个节点,返回下一个节点即可;
不过越做发现问题越多,因为很难对中序遍历进行魔改,更何况给定的节点有可能需要返回上一个节点;
无奈之下去看了题解,发现题解真有意思:
题解给出了两种思路,一种是在笔试的情况下,一种是在面试的情况下:
笔试的情况下,只要能得到答案就好,因此首先从当前节点回溯至根节点,再进行中序遍历,得到结果;
这个办法确实简单粗暴,不过效率不高,适合笔试;
面试的话需要设计时间复杂度低的算法,题解对所有的情况进行了分类讨论:
- 当前节点有右子树,那么下一个节点就是右子树的最左节点,如果不存在就是右子树自身;
- 当前节点不存在右子树,那么下一个节点就网上搜索,直到当前节点是父节点的左子树;
- 最后一种情况就是当前为最后的节点,返回空指针;
不得不说,我确实忽略了分类讨论的方法,以为会很复杂,但其实只要画图列出所有情况就能轻松找到规律:
代码
/*
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
*/
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
TreeLinkNode* node = pNode;
if (!node) return nullptr;
// 有右子树的情况
if (node->right) {
node = node->right;
while (node->left) {
node = node->left;
}
return node;
}
// 当前无右子树的情况
while (node->next) {
if (node == node->next->left) {
return node->next;
}
node = node->next;
}
// 为最后一个节点
return nullptr;
}
};