《剑指 Offer》专项突破 - 面试题 43 : 在完全二叉树中添加节点(两种方法 + C++ 实现)

目录

前言

方法一

方法二


 


前言

题目链接:LCR 043. 完全二叉树插入器 - 力扣(LeetCode)

题目

在完全二叉树中,除最后一层之外其他层的节点都是满的(第 n 层有 个节点)。最后一层的节点可能不满,该层所有的节点尽可能向左靠拢。例如,下图中的 4 棵二叉树均为完全二叉树。实现数据结构 CBTInserter 有如下 3 种方法。

  • 构造函数 CBTInserter(TreeNode* root),用一棵完全二叉树的根节点初始化该数据结构。

  • 函数 insert(int v) 在完全二叉树中添加一个值为 v 的节点,并返回被插入节点的父节点。例如,在下图 (a) 所示的完全二叉树中添加一个值为 7 的节点之后,二叉树如下图 (b) 所示,并返回节点 3。在下图 (b) 所示的完全二叉树中添加一个值为 8 的节点之后,二叉树如下图 (c) 所示,并返回节点 4。在下图 (c) 所示的完全二叉树中添加节点 9 会得到下图 (d) 所示的二叉树并返回节点 4。

  • 函数 get_root() 返回完全二叉树的根节点。

《剑指 Offer》专项突破 - 面试题 43 : 在完全二叉树中添加节点(两种方法 + C++ 实现)_第1张图片


方法一

在完全二叉树中添加新节点顺序看起来是从上到下按层从左到右添加的,这就是典型的二叉树广度优先搜索的顺序。我们可以每次在完全二叉树中按照广度优先搜索的顺序找出第 1 个左子节点或右子节点还有空缺的节点。如果它没有左子节点,那么新的节点就作为它的左子节点;如果它没有右子节点,那么新的节点就作为它的右子节点

例如,在上图 (a) 所示的完全二叉树中添加新的节点 7 时,节点 3 是按照广度优先搜索的顺序找到的第 1 个缺少子节点的节点,它已经有左子节点但没有右子节点,因此节点 7 就插入节点 3 的右子节点的位置。同样,在上图 (b) 所示的完全二叉树中添加新的节点 8 时,节点 4 是按照广度优先搜索的顺序找到的第 1 个缺少子节点的节点,它既没有左子节点也没有右子节点,因此节点 8 插入节点 4 的左子节点的位置。

接下来考虑效率优化。在完全二叉树中添加节点时需要按照广度优先搜索的顺序找出第 1 个缺少子节点的节点。其实没有必要在每次插入新的节点时都从完全二叉树的根节点开始从头进行广度优先搜索

例如,在上图 (a) 所示的完全二叉树中添加新的节点 7 时,从根节点开始按照广度优先搜索的顺序找出节点 3 是第 1 个缺少子节点的节点,由此可知,在节点 3 之前被遍历过的所有节点(节点 1 和节点 2)的左右子节点都已经存在,并且当节点 7 插入节点 3 的右子节点的位置之后节点 3 的左右子节点都已经存在。下次再插入新的节点时,就没有必要从根节点开始,而是跳过节点 1、节点 2 和节点 3,直接从节点 4 开始查找第 1 个还缺少子节点的节点。

class CBTInserter {
public:
    CBTInserter(TreeNode* root) {
        this->root = root;
​
        q.push(root);
        TreeNode* front = root;
        while (front->left && front->right)
        {
            q.pop();
            q.push(front->left);
            q.push(front->right);
            front = q.front();
        }
    }
    
    int insert(int v) {
        TreeNode* newNode = new TreeNode(v);
        TreeNode* front = q.front();
        if (front->left == nullptr)
        {
            front->left = newNode;
        }
        else
        {
            front->right = newNode;
            q.pop();
            q.push(front->left);
            q.push(front->right);
        }
        return front->val;
    }
    
    TreeNode* get_root() {
        return root;
    }
private:
    TreeNode* root;
    queue q;
};


方法二

class CBTInserter {
public:
    CBTInserter(TreeNode* root) {
        queue q;
        q.push(root);
        while (!q.empty())
        {
            TreeNode* front = q.front();
            q.pop();
            treeV.push_back(front);
            if (front->left)
                q.push(front->left);
            
            if (front->right)
                q.push(front->right);
        }
    }
    
    int insert(int v) {
        TreeNode* newNode = new TreeNode(v);
        treeV.push_back(newNode);
​
        int parent = (treeV.size() - 1 - 1) / 2;
        TreeNode* node = treeV[parent];
        if (node->left == nullptr)
            node->left = newNode;
        else
            node->right = newNode;
        return node->val;
    }
    
    TreeNode* get_root() {
        return treeV[0];
    }
private:
    vector treeV;
};

你可能感兴趣的:(数据结构,c++,算法,数据结构,面试,开发语言)