Problem: 114. 二叉树展开为链表
思路
因为需要将左子树插入到右子树中,所以采取先右后左的策略,这样使得插入之后不会打乱原有右子树的相对顺序。
解题方法
类似于Morris遍历,不过先右后左,使得左子树插入右子树时,右子树已经展开完成,且顺序固定。具体为:将一个存在左子树的节点,将其左子树插入到其与右子树之间(如果存在右子树),否则直接将其左子树变为右子树。依次从底层递归向上。
复杂度
- 时间复杂度:
O(n),每个节点均需判断
- 空间复杂度:
O(1)
Code
/**
* 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) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if(!root)
return;
dfs(root);
}
void dfs(TreeNode* root) {
if(root->right)//先右子树
dfs(root->right);
if(root->left)//后左子树
dfs(root->left);
if(root->left) {
TreeNode* p = root->left;
while(p->right)//找到左子树的最右子树,类似于Morris遍历
p = p->right;
if(root->right) {//如果存在该节点的右子树则需要插入到其中
p->right = root->right;
}
root->right = root->left;
root->left = NULL;//注意将左子树会空,否则会有heap-use-after-free 问题
}
}
};