114. 二叉树展开为链表

要求:按前序拆成链表
思路:
错误示范:访问2左二子3时已经把2右儿子4改成3了,4丢了

class Solution {
public:
    TreeNode* pre;
    void preorder(TreeNode* root){
        pre->right=root;//可能还会回到pre右儿子这里不能改
        pre=root;
        if(root->left)preorder(root->left);
        if(root->right)preorder(root->right);
        root->left=nullptr;
    }
    void flatten(TreeNode* root) {
        if(!root)return;
        TreeNode* head=new TreeNode(-1);
        pre=head;
        preorder(root);
    }
};

正确示范,既然丢了就先存起来。最后rootleft可以换成在pre处就改了

class Solution {
public:
    TreeNode* pre;
    void preorder(TreeNode* root){
        pre->right=root;
        pre=root;
        TreeNode* l=root->left;
        TreeNode* r=root->right;
        if(l)preorder(l);
        if(r)preorder(r);
        root->left=nullptr;
    }
    void flatten(TreeNode* root) {
        if(!root)return;
        TreeNode* head=new TreeNode(-1);
        pre=head;
        preorder(root);
    }
};

法二:倒过来遍历不用考虑丢失的问题

class Solution {
public:
    TreeNode* pre=nullptr;
    void rpreorder(TreeNode* root){
        if(root->right)rpreorder(root->right);
        if(root->left)rpreorder(root->left);
        root->left=nullptr;
        root->right=pre;
        pre=root;
    }
    void flatten(TreeNode* root) {
        if(!root)return;
        rpreorder(root);
    }
};

法三:先序遍历迭代写法是先入栈所有左节点,然后弹出一个换右节点,循环。另一种写法是类似层序,右孩子比左孩子入栈

class Solution {
public:
    void flatten(TreeNode* root) {
        if(!root)return;
        stack<TreeNode*> s;
        TreeNode* pre=nullptr;
        s.push(root);
        while(!s.empty()){
            TreeNode* tmp=s.top();
            s.pop();
            if(pre){
                pre->right=tmp;
                pre->left=nullptr;
            }
            pre=tmp;
            if(tmp->right)s.push(tmp->right);
            if(tmp->left)s.push(tmp->left);
        }
    }
};

法四:想象。

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值