46 二叉树展开为链表

二叉树展开为链表

    • 理解题意:前序遍历的N种写法
    • 题解1 前序遍历
    • 题解2 反前序遍历(代码简洁)
    • 题解3 类似旋转的方法
    • 题解4 迭代
    • 题解5 同时遍历+改左右子树

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

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

46 二叉树展开为链表_第1张图片
提示:

  • 树中结点数在范围 [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;
        }
    }
};

46 二叉树展开为链表_第2张图片

题解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;
    }
};

46 二叉树展开为链表_第3张图片

题解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;
        }
    }
};

46 二叉树展开为链表_第4张图片

题解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;
        }
    }
};

46 二叉树展开为链表_第5张图片

题解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;
        }
    }

46 二叉树展开为链表_第6张图片

你可能感兴趣的:(二叉树,HOT100,搜索,数据结构,leetcode,算法)