力扣-114-二叉树展开为链表

传送门

题目分析:将二叉树展开为单链表,单链表中各个节点的顺序即为二叉树前序遍历的顺序,故可以通过二叉树的前序遍历获得单链表各个节点的顺序。但是将二叉树转化为单链表后就破坏了二叉树的结构,所以可以保存前序遍历的结果,然后分别依次更改节点的左右节点的信息。

二叉树的前序遍历用递归的方法,代码如下:

/**
 * 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 {
public:
    void flatten(TreeNode* root) {
        vector<TreeNode*> tree;
        preorder(root, tree);
        
        int num = tree.size();
        for(int i = 1; i < num; i++){  //依次更改每个节点的左右节点信息
            TreeNode* pre = tree[i - 1]; //tree.at(i - 1);
            TreeNode* curr = tree[i];
            pre->left = NULL;
            pre->right = curr;
        }
    }
    
    void preorder(TreeNode* root, vector<TreeNode*>& tree){  //前序遍历
        if(root != NULL) {
            tree.push_back(root);
            preorder(root->left, tree);
            preorder(root->right, tree);
        }
    }
};

 

 

方法二:如何在不存储节点增加额外空间的前提下,空间复杂度为$O(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 {
public:
    void flatten(TreeNode* root) {
        TreeNode* curr = root;
        while(curr != NULL) {
            if (curr->left != NULL) {
                TreeNode* Left = curr->left;
                TreeNode* temp = Left;
                while(temp->right != NULL){  //找到左子树中最右边的节点
                    temp = temp -> right;
                }
                temp->right = curr->right;
                curr->right = Left;
                curr->left = NULL;
            }
            curr = curr->right; //左子树为空,直接移动到下一个当前节点
        }
    }
};

 

posted @ 2020-08-03 10:04  Peterxiazhen  阅读(153)  评论(0编辑  收藏  举报