题目描述
给定一个二叉树,原地将它展开为链表。
给定二叉树:
1
/ \
2 5
/ \ \
3 4 6
将其展开为:
1
\
2
\
3
\
4
\
5
\
6
解题思路
《剑指offer》上第36题的解题思路是进行“中序”展开,开始时认为此题可以借鉴《剑指offer》上的思路进行“前序”展开。 => 上述思路完全不着调,《剑指offer》中的做法仅仅适用于“中序遍历”,在前序遍历时如果采用上述方法会在递归过程中(提前)修改了树中节点的左右指针,导致出错。
整体思路如下:
1
/ \
2 5
/ \ \
3 4 6
//将 1 的左子树插入到右子树的地方
1
\
2 5
/ \ \
3 4 6
//将原来的右子树接到左子树的最右边节点
1
\
2
/ \
3 4
\
5
\
6
//将 2 的左子树插入到右子树的地方
1
\
2
\
3 4
\
5
\
6
//将原来的右子树接到左子树的最右边节点
1
\
2
\
3
\
4
\
5
\
6
......
-
后序遍历:用后序遍历解题
def flatten(self, root: TreeNode): if root is None: return self.flatten(root.left) self.flatten(root.right) if root.left: pre = root.left while pre.right: pre = pre.right pre.right = root.right root.right = root.left root.left = None
-
非递归,不使用辅助空间及全局变量:此解法无需申请栈,也不用全局变量,是真正的
In-Place
解法。比较巧妙,代码看题解。(一般来说树的问题推荐写递归代码)
参考代码
递归解法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if(root != nullptr){
flatten(root->left);
flatten(root->right);
TreeNode* pMostRight = nullptr;
if(root->left){
pMostRight = root->left;
while(pMostRight->right)
pMostRight = pMostRight->right;
pMostRight->right = root->right;
root->right = root->left;
root->left = nullptr; // 不要忘记加
}
}
}
};
非递归解法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
while (root != nullptr) {
if (root->left != nullptr) {
auto most_right = root->left; // 如果左子树不为空, 那么就先找到左子树的最右节点
while (most_right->right != nullptr)
most_right = most_right->right; // 找最右节点
most_right->right = root->right; // 然后将根的右孩子放到最右节点的右子树上
root->right = root->left; // 这时候根的右孩子可以释放, 因此令左孩子放到右孩子上
root->left = nullptr; // 将左孩子置为空(不要忘记加)
}
root = root->right; // 继续下一个节点
}
return;
}
};