【力扣-二叉树】20、二叉搜索树中的插入操作(701)

176 阅读3分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

701. 二叉搜索树中的插入操作

题目描述

给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果

 

示例 1:

输入: root = [4,2,7,1,3], val = 5
输出: [4,2,7,1,3,5]
解释: 另一个满足题目要求可以通过的树是:

示例 2:

输入: root = [40,20,60,10,30,50,70], val = 25
输出: [40,20,60,10,30,50,70,null,null,25]

示例 3:

输入: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出: [4,2,7,1,3,5]

解析

递归法

  • 递归三要素
    • 1、确定递归函数的参数与返回值
      • 参数:节点、要插入节点的值
      • 返回值:可有、可无
    • 2、确定递归的终止条件
      • 找到遍历的节点为NULL时,就是要插入的位置,并把插入的节点返回
    • 3、单层递归的逻辑
      • 利用二叉搜索树的性质,不需要遍历整棵树

有返回值

// 递归函数有返回值
class Solution
{
public:
    TreeNode *insertIntoBST(TreeNode *root, int val)
    {
        // 遇到空节点,将新节点插入
        if (root == NULL)
        {
            TreeNode *node = new TreeNode(val);
            return node;
        }

        // 要插入节点的值小于当前遍历节点的值
        // 向左子树遍历
        if (root->val > val)
        {
            root->left = insertIntoBST(root->left, val);
        }
        // 向右子树遍历
        if (root->val < val)
        {
            root->right = insertIntoBST(root->right, val);
        }

        return root;
    }
};

无返回值

// 递归函数无返回值
class Solution1
{
private:
    TreeNode *parent;
    void traversal(TreeNode *cur, int val)
    {
        // 若找到空节点
        if (cur == NULL)
        {
            // 创建要插入的新节点
            TreeNode *node = new TreeNode(val);

            // 判断父节点的值与要插入节点值的大小
            // 确定新节点的插入位置
            if (parent->val < val)
            {
                parent->right = node;
            }
            else
            {
                parent->left = node;
            }
            return;
        }
        // 若没有找到空节点
        // 继续查找
        parent = cur;

        //向左查找
        if (cur->val > val)
        {
            traversal(cur->left, val);
        }
        traversal(cur->right, val);
        return;
    }

public:
    TreeNode *insertIntoBST(TreeNode *root, int val)
    {
        parent = new TreeNode(0);
        if (root == NULL)
        {
            root = new TreeNode(val);
            return root;
        }

        traversal(root, val);

        return root;
    }
};

迭代法

  • 判断根节点是否为空,若为空,将要插入节点的值赋予根节点,返回根节点
  • 根节点不为空,使用栈存放要遍历的节点
  • 栈中存放的节点满足值小于要插入节点的值或大于要插入节点的值
  • 判断遍历节点的左右子树是否为空,来插入新的节点
class Solution
{
public:
    TreeNode *insertIntoBST(TreeNode *root, int val)
    {
        // 判断根节点是否为空
        if (root == NULL)
        {
            root = new TreeNode(val);
            return root;
        }

        stack<TreeNode *> st;
        TreeNode *pre;

        st.push(root);

        // 遍历栈中的节点
        while (!st.empty())
        {
            TreeNode *cur = st.top();
            st.pop();

            // 左子树
            if (cur->val > val)
            {
                if (cur->left)
                {
                    st.push(cur->left);
                }
                else
                {
                    // 左子树为空,则将新节点插入到左子树的位置
                    cur->left = new TreeNode(val);
                    return root;
                }
            }

            if (cur->val < val)
            {
                if (cur->right)
                {
                    st.push(cur->right);
                }
                else
                {
                    // 右子树为空,则将新节点插入到左子树的位置
                    cur->right = new TreeNode(val);
                    return root;
                }
            }
        }
        return root;
    }
};