题目概述
原题链接
树定义如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
思考过程
- 由于题目要求展开后的单链表应该同样使用
TreeNode
,说明这题的本质是构造一颗只有右子树的树,节点顺序为原树的前序遍历
- 如示例1一颗复杂的树,有点感到无从下手,但如果这棵树只有
根节点、左孩子、右孩子
是不是就容易解决多了
1
root.left / \ root.right
2 3
- 如上一步所示,我们只需要将根节点的右孩子指针指向左孩子,再将右孩子拼接到左孩子下,即可完成。需要注意的是
- 在将根节点的右孩子指针指向左孩子前,需要一个临时指针指向右孩子,即
TreeNode* temp=root.right
,否则右孩子信息将会丢失,无法进行后续拼接 - 当将根节点的右孩子指针指向左孩子时,此时根节点
1
的两个指针都指向了左孩子2
,故需要断开原来的连接,即root.left=null
- 然后递归找到目前根节点指向的孩子
2
的最后一个节点,将用临时指针指向的节点3
拼接上去,即可完成这棵树的链表展开了
- 在将根节点的右孩子指针指向左孩子前,需要一个临时指针指向右孩子,即
- 既然一个简单树可以这么做,很显然可以利用
递归的思想
解决一颗复杂的树
代码实现
void flatten(TreeNode* root) {
// 特殊情况
if (root == nullptr) return ;
// 捋直左子树
flatten(root->left);
// 捋直右子树
flatten(root->right);
// 临时指针指向右子树
TreeNode* temp = root->right;
// 将左子树接到右子树下,即将右子树的指针指向左子树
root->right = root->left;
// 将左子树置空
root->left = nullptr;
// 找到当前右子树(拼接了左子树的右子树)的最后一个节点
while(root->right != nullptr) {
root = root->right;
}
// 把右子树(原来的)拼接到当前右子树(拼接了左子树的右子树)下
root->right = temp;
}