解法一:暴力解法
据题意,「某结点的下一个结点」定义为「中序遍历」后的下一个结点。因此暴力解法的步骤为:
- 根据输入的结点以及next指针,先求得二叉树的根结点root;
- 利用root进行二叉树的中序遍历,并定义数组储存中序遍历的结果;
- 遍历该数组,得到「下一个结点」。
注意:二叉树的中序遍历步骤为:先遍历左子树,再访问根结点,再遍历右子树。因此可通过递归较为方便地实现二叉树的中序遍历。
代码如下:
/*
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) {
if (!pNode)
return NULL;
// 寻找根结点
TreeLinkNode* root = pNode;
while (root->next) {
root = root->next;
} // 完成while循环后,root即指向根结点
vector<TreeLinkNode*> nodeVec;
inorder(root, nodeVec); // 中序遍历
for (int i = 0; i < nodeVec.size(); i ++) {
if (nodeVec[i] == pNode && i + 1 < nodeVec.size())
return nodeVec[i + 1]; // 下一个结点为所求结点
}
return NULL; // 若该结点无下一结点,返回NULL
}
void inorder(TreeLinkNode* root, vector<TreeLinkNode*> &nodeVec) {
if (!root)
return;
inorder(root->left, nodeVec); // 访问左子树
nodeVec.push_back(root); // 访问根结点
inorder(root->right, nodeVec); // 访问右子树
}
}; 在进行中序遍历时,遍历到树的所有结点,因此复杂度为O(N);在进行数组遍历时,复杂度为O(N),故总时间复杂度为O(N)。
此解法定义数组存储中序遍历结果,故空间复杂度为O(N)。
解法二:利用中序遍历性质
解法一进行了一整个中序遍历,然而题目仅要求「下一个结点」,因此进行「整个」中序遍历是不必要的。
解法二的思路利用了中序遍历的性质。中序遍历的步骤可表示为LTR,其中L代表左子树,T代表根结点,R代表右子树,即:先访问某结点的左子树,再访问该结点,再访问该结点的右子树。
「某结点的下一个结点」仅有二种情况:
- 若该结点存在右子树,则「下一个结点」为「该结点右子树的最左孩子」;
- 若该结点不存在右子树,则「下一个结点」为「该结点的第一个右父结点」。
下面结合图例分别对上述二种情况进行阐述。
对于情况一,步骤如下:
- 结点1存在右子树,则在进行中序遍历时,在访问结点1后,必将访问「该结点的右子树」,即以2为根结点的子树。
- 在访问该子树时,会先访问结点2的左子树,即以3为根结点的子树。
- 在访问该子树时,会先访问结点3的左子树,即结点4。
以此类推,在通过中序遍历访问某结点的右子树时,会从其「右子树的最左孩子开始」。
对于情况二,步骤如下:
- 结点1不存在右子树,则其『下一个结点』,设为p,一定满足条件:结点1位于p结点的左子树上。因此,需要寻找其第一个「右父亲」;
- 结点1不存在右父亲,故向上寻找,即寻到结点2;
- 结点2不存在右父亲,故向上寻找,即寻到结点3;
- 结点3的右父亲为结点4。结点4即为所求。可见,待求结点(结点1)位于结点4的左子树上。
故得出结论:若该结点不存在右子树,则「下一个结点」为「该结点的第一个右父结点」。
代码如下:
/*
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) {
if (!pNode)
return NULL;
// 若该结点存在右子树
if (pNode->right) {
TreeLinkNode* rightChild = pNode->right;
// 寻找右子树上的最左孩子
while (rightChild->left)
rightChild = rightChild->left;
return rightChild;
}
// 若不存在右子树,寻找第一个右父亲
while (pNode->next) {
if (pNode->next->left == pNode)
return pNode->next;
pNode = pNode->next;
}
return NULL;
}
}; 该方法最坏情况如图所示,对于1号结点,需要不断向上寻找其第一个右父亲,故需要遍历整棵树,时间复杂度为O(N);该方法不需要引入额外空间,空间复杂度为O(1)。



京公网安备 11010502036488号