【力扣-二叉树】22、将有序数组转换为二叉搜索树(108)

146 阅读2分钟

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

108. 将有序数组转换为二叉搜索树

题目描述

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

输入: nums = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: [0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

输入: nums = [1,3]
输出: [3,1]
解释: [1,3][3,1] 都是高度平衡二叉搜索树。

解析

递归法

/**
 * @brief 递归法
 * 递归三部曲:
 *  1、确定递归函数的参数与返回值
 *      使用递归函数的返回值来构造节点的左右孩子
 *      参数:传入的数组nums,左下标 left , 右下标 right。
 *      TreeNode *traversal(vector<int> &nums , int left, int right)
 *  2、确定递归终止条件
 *      当下标值 left > right 时就是空节点了
 *      if(left>right) return nullptr; 
 *  3、确定单层循环的逻辑
 *      (1)取数组元素的中间位置, int mid = (left+right) / 2
 *          但是若left和right都是最大int ,那么操作就会越界,
 *          所以中间元素的位置可以由:int mid = left+((right-left) / 2)来获得。
 *          对于int mid = left + ((right-left)/2); 这种写法,当数组为偶数时,中间位置有两个元素,取左边的
 *      (2)取到中间位置的元素后,构造节点 : TreeNode *root = new TreeNode(nums[mid]) ;
 *          root的左孩子: root->left = traversal(nums,left,mid-1);
 *          root的右孩子: root->right = traversal(nums,mid+1,right);
 *          (此处体现出返回值的作用)
 *          最后返回root .
 */

代码

class Solution
{
public:
    TreeNode *sortedArrayToBST(vector<int> &nums)
    {
        int size = nums.size();
        // 数组为空,直接返回空
        if (size == 0)
        {
            return nullptr;
        }
        return traversal(nums, 0, size - 1);
    }

private:
    TreeNode *traversal(vector<int> &nums, int left, int right)
    {
        if (left > right)
        {
            return nullptr;
        }

        // 取数组的中间元素作为根节点
        int mid = left + ((right - left) / 2);
        TreeNode *root = new TreeNode(nums[mid]);
        // 左孩子
        root->left = traversal(nums, left, mid - 1);
        // 右孩子
        root->right = traversal(nums, mid + 1, right);

        // 返回根节点
        return root;
    }
};

迭代法


/**
 * @brief 迭代法
 * 使用三个队列来实现
 *  1、队列1 存放遍历的节点
 *  2、队列2 存放左区间下标
 *  3、队列3 存放右区间下标
 * 
 *  迭代更新三个队列的同时创建二叉树
 * 
 */

代码

class Solution
{
public:
    TreeNode *sortedArrayToBST(vector<int> &nums)
    {
        int size = nums.size();
        if (size == 0)
        {
            return nullptr;
        }

        // 存放遍历的节点
        queue<TreeNode *> q_nodes;
        // 存放左区间的下标
        queue<int> q_left;
        // 存放右区间的下标
        queue<int> q_right;

        // 初始根节点
        TreeNode *root = new TreeNode(0);
        q_nodes.push(root);
        q_left.push(0);
        q_right.push(size - 1);

        while (!q_nodes.empty())
        {
            TreeNode *node = q_nodes.front();
            q_nodes.pop();

            int left = q_left.front();
            q_left.pop();

            int right = q_right.front();
            q_right.pop();

            // 取数组中间的索引
            int mid = left + ((right - left) / 2);
            // 数组中间的元素
            node->val = nums[mid];

            // 左区间
            if (left <= mid - 1)
            {
                node->left = new TreeNode(0);
                q_nodes.push(node->left);
                q_left.push(left);
                q_right.push(mid - 1);
            }
            // 右区间
            if (right >= mid + 1)
            {
                node->right = new TreeNode(0);
                q_nodes.push(node->right);
                q_left.push(mid + 1);
                q_right.push(right);
            }
        }
        return root;
    }
};