114. 二叉树展开为链表 (四种解法)

解法1:递归,从下至上先将深层次的左右子树转化为链表

关键步骤:

1:对带有左子树的节点,将其左右子树展开为链表。

2:找左子树最右的叶子节点,将右子树挂左子树最右叶子上。

3:将左子树换成右子树,左子树置空。

class Solution {
public:
    void flatten(TreeNode* root) {
        if (NULL == root)
            return;
        
        flatten(root->right);              //将右子树展开为链表
        if (NULL == root->left)            //若左子树为空,不用再操作
            return;
        flatten(root->left);               //将左子树展开为链表

        TreeNode *rightTail = root->left;
        while (rightTail->right)
            rightTail = rightTail->right;  //找左子树最右的叶节点
        
        rightTail->right = root->right;    //右子树挂左子树最右叶子上
        root->right = root->left;          //左子树换成右子树
        root->left = NULL;                 //左子树置空
    }
};

解法2:非递归,从上至下一层层消除左子树

关键步骤:

1:从root层开始,一层层消除左子树

2:找左子树最右的叶子节点,将右子树挂左子树最右叶子上。

3:将左子树换成右子树,左子树置空。

class Solution {
public:
    void flatten(TreeNode* root) {
        if (NULL == root)
            return;
        
        TreeNode *node, *rightTail;
        while (root) {
            if (NULL != root->left) {
                node = root->left;                 //对左子树进行操作

                rightTail = node;
                while (rightTail->right)
                    rightTail = rightTail->right;  //找左子树的最右叶子节点
                rightTail->right = root->right;    //将右子树接到上述叶子节点的右子节点上

                root->right = root->left;          //将左子树改成右子树
                root->left = NULL;                 //左子树置空
            }
            root = root->right;
        }
    }
};

解法3:利用栈,先序遍历,根节点开始一点点穿下一个较大的数,大数最后处理

关键步骤:

1:用一个pre指针指向当前链表最后一个节点。

2:大数的右子树先入栈,循环处理后,数越大,压的越深。

3:pre指针先连接左子树中的根节点(未处理的最小数)。

         循环处理后,通过pre指针一个个地串起了左子树的最小数(左子树左子节点),然后再串左子树的次小数(左子树右子节点),最后串右子树的较大数。

class Solution {
public:
    void flatten(TreeNode* root) {
        if (NULL == root)
            return;
        
        stack<TreeNode*> sta;
        sta.push(root);
        TreeNode *pre = NULL, *node;
        while (!sta.empty()) {
            node = sta.top();
            sta.pop();

            if (NULL != pre) {
                pre->right = node;
                pre->left = NULL;
            }

            if (node->right)           //先将大数压入栈,最后再处理
                sta.push(node->right);
            if (node->left)            //先处理左子树的小数,后入先出
                sta.push(node->left);
            
            pre = node;                //指向当前最小数的节点,一点一点连接较大数到右子树上
        }
    }
};

        这里,比较感谢牛客码友的解析。欢迎探讨!

解法四:若有左子树,将左子树转到右子树上,右子树若有则压栈

class Solution {
public:
    void flatten(TreeNode* root) {
        if (NULL == root)
            return;
        
        stack<TreeNode*> sta;
        while (root || !sta.empty()) {
            if (root->left) {                //有左子树情况
                if (root->right)             //右子树入栈
                    sta.push(root->right);
                root->right = root->left;
                root->left = NULL;
            }
            if (root->right)                //有节点非空,就往下走一步
                root = root->right;
            else {
                if (sta.empty())           //右节点空,备用栈空,结束
                    break;

                root->right = sta.top();   //从栈里找节点挂上去
                sta.pop();
            }
        }
    }
};

         看示例,想到的一种最直接的方法!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值