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
    评论
第一篇 面试题 ................................................................................ 8 1.1. 简介 ............................................................................................................... 8 1.2. 面试题集合(一) .......................................................................................... 8 1.2.1. 把二元查找树转变成排序的双向链表.................................................... 8 1.2.2. 下排每个数都是先前上排那十个数在下排出现的次数 ..........................11 1.2.3. 设计包含 min 函数的栈 ...................................................................... 14 1.2.4. 求子数组的最大和.............................................................................. 20 1.2.5. 在二元树中找出和为某一值的所有路径 .............................................. 22 1.2.6. Top K 算法详细解析---百度面试 ......................................................... 29 1.2.7. 翻转句子中单词的顺序....................................................................... 31 1.2.8. 判断整数序列是不是二元查找树的后序遍历结果 ................................ 33 1.2.9. 查找最小的 K 个元素-使用最大堆....................................................... 35 1.2.10. 求二叉树中节点的最大距离................................................................ 37 1.3. 面试题集合(二) ........................................................................................ 40 1.3.1. 求 1+2+…+n....................................................................................... 40 1.3.2. 输入一个单向链表,输出该链表中倒数第 k 个结点............................. 44 1.3.3. 输入一个已经按升序排序过的数组和一个数字.................................... 46 1.3.4. 输入一颗二元查找树,将该树转换为它的镜像.................................... 48 1.3.5. 输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往 右的顺序打印................................................................................................... 49 1.3.6. 在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b 52 1.3.7. n 个数字(0,1,…,n-1)形成一个圆圈 .................................................. 53 1.3.8. 定义 Fibonacci 数列 ............................................................................ 58 1.3.9. 左移递减数列查找某一个数.........................................

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值