• 46 二叉树展开为链表



    给你二叉树的根结点 root ,请你将它展开为一个单链表:

    展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null
    展开后的单链表应该与二叉树先序遍历顺序相同。

    在这里插入图片描述
    提示:

    • 树中结点数在范围 [0, 2000] 内
    • -100 <= Node.val <= 100

    理解题意:前序遍历的N种写法

    题解1 前序遍历

    /**
     * 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 {
        vector<TreeNode*> arr;
    public:
        void dfs(TreeNode* root){
            if(! root) return;
            arr.push_back(root);
            dfs(root->left);
            dfs(root->right);
        } 
        void flatten(TreeNode* root) {
            if(! root) return;
            dfs(root);
            for(int i = 1; i < arr.size(); i++){
                root->right = arr[i];
                root->left = nullptr;
                root = root->right;
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    题解2 反前序遍历(代码简洁)

    class Solution {
        TreeNode* preNode;
    public:
        void flatten(TreeNode* root) {
            if (! root) return;
            // right先压栈(后面弹)
            flatten(root->right);
            flatten(root->left);
            // 第一次执行 root是前序遍历的最后访问的结点
            root->left = NULL;
            root->right = preNode;
            preNode = root;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    题解3 类似旋转的方法

    class Solution {
        TreeNode* preNode;
    public:
        void flatten(TreeNode* root) {
            TreeNode *curr = root;
            while (curr != nullptr) {
                if (curr->left != nullptr) {
                    auto next = curr->left;
                    auto predecessor = next;
                    while (predecessor->right != nullptr) {
                        predecessor = predecessor->right;
                    }
                    predecessor->right = curr->right;
                    curr->left = nullptr;
                    curr->right = next;
                }
                curr = curr->right;
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    题解4 迭代

    class Solution {
        TreeNode* preNode;
    public:
        void flatten(TreeNode* root) {
            auto v = vector<TreeNode*>();
            auto stk = stack<TreeNode*>();
            TreeNode *node = root;
            while (node != nullptr || !stk.empty()) {
                while (node != nullptr) {
                // 前序遍历: 动作放在最前面
                    v.push_back(node);
                    stk.push(node);
                    node = node->left;
                }
                node = stk.top(); 
                stk.pop();
                node = node->right;
            }
            int size = v.size();
            for (int i = 1; i < size; i++) {
                auto prev = v.at(i - 1), curr = v.at(i);
                prev->left = nullptr;
                prev->right = curr;
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

    题解5 同时遍历+改左右子树

    void flatten(TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            auto stk = stack<TreeNode*>();
            stk.push(root);
            TreeNode *prev = nullptr;
            while (!stk.empty()) {
                TreeNode *curr = stk.top(); 
                stk.pop();
                if (prev != nullptr) {
                    prev->left = nullptr;
                    prev->right = curr;
                }
                TreeNode *left = curr->left, *right = curr->right;
                // 防止脏数据,原数据先放进stack里
                if (right != nullptr) {
                    stk.push(right);
                }
                if (left != nullptr) {
                    stk.push(left);
                }
                //迭代
                prev = curr;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

  • 相关阅读:
    sort内部实现原理
    Spring核心思想
    MySql⭐一、配置MySql数据库,并创建一个表单
    AI 帮忙找 Bug,英特尔开源代码编程工具ControlFlag
    死锁的3种死法
    最新版手机软件App下载排行网站源码/App应用商店源码
    Java -- 每日一问:谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
    C语言 AES加解密
    jsencrypt 公私钥解加密
    Laravel 创建自己的 Facade 扩展 geoip 根据 IP 获取国家、地域、城市信息
  • 原文地址:https://blog.csdn.net/qq_43402798/article/details/133658440