返回介绍

Convert Sorted Array to Binary Search Tree

发布于 2025-02-22 13:01:30 字数 3488 浏览 0 评论 0 收藏 0

Source

Given an array where elements are sorted in ascending order,
convert it to a height balanced BST.

Given a sorted (increasing order) array,
Convert it to create a binary tree with minimal height.

Example
Given [1,2,3,4,5,6,7], return

   4
   /   \
  2   6
 / \  / \
1   3  5   7
Note
There may exist multiple valid solutions, return any of them.

题解 - 折半取中

将二叉搜索树按中序遍历即可得升序 key 这个容易实现,但反过来由升序 key 逆推生成二叉搜索树呢?按照二叉搜索树的定义我们可以将较大的 key 链接到前一个树的最右侧节点,这种方法实现极其简单,但是无法达到本题「树高平衡-左右子树的高度差绝对值不超过 1」的要求,因此只能另辟蹊径以达到「平衡二叉搜索树」的要求。

要达到「平衡二叉搜索树」这个条件,我们首先应从「平衡二叉搜索树」的特性入手。简单起见,我们先考虑下特殊的满二叉搜索树,满二叉搜索树的一个重要特征就是各根节点的 key 不小于左子树的 key ,而小于右子树的所有 key;另一个则是左右子树数目均相等,那么我们只要能将所给升序序列分成一大一小的左右两半部分即可满足题目要求。又由于此题所给的链表结构中仅有左右子树的链接而无指向根节点的链接,故我们只能从中间的根节点进行分析逐层往下递推直至取完数组中所有 key, 数组中间的索引自然就成为了根节点。由于 OJ 上方法入口参数仅有升序序列,方便起见我们可以另写一私有方法,加入 startend 两个参数,至此递归模型初步建立。

C++

/**
 * Definition for binary tree
 * struct TreeNode {
 *   int val;
 *   TreeNode *left;
 *   TreeNode *right;
 *   TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
  TreeNode *sortedArrayToBST(vector<int> &num) {
    if (num.empty()) {
      return NULL;
    }

    return middleNode(num, 0, num.size() - 1);
  }

private:
  TreeNode *middleNode(vector<int> &num, const int start, const int end) {
    if (start > end) {
      return NULL;
    }

    TreeNode *root = new TreeNode(num[start + (end - start) / 2]);
    root->left = middleNode(num, start, start + (end - start) / 2 - 1);
    root->right = middleNode(num, start + (end - start) / 2 + 1, end);

    return root;
  }
};

Java

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *   public int val;
 *   public TreeNode left, right;
 *   public TreeNode(int val) {
 *     this.val = val;
 *     this.left = this.right = null;
 *   }
 * }
 */
public class Solution {
  /**
   * @param A: an integer array
   * @return: a tree node
   */
  public TreeNode sortedArrayToBST(int[] A) {
    if (A == null || A.length == 0) return null;

    return helper(A, 0, A.length - 1);
  }

  private TreeNode helper(int[] nums, int start, int end) {
    if (start > end) return null;

    int mid = start + (end - start) / 2;
    TreeNode root = new TreeNode(nums[mid]);
    root.left = helper(nums, start, mid - 1);
    root.right = helper(nums, mid + 1, end);

    return root;
  }
}

源码分析

从题解的分析中可以看出中间根节点的建立至关重要!由于数组是可以进行随机访问的,故可取数组中间的索引为根节点,左右子树节点可递归求解。虽然这种递归的过程和「二分搜索」的模板非常像,但是切记本题中根据所给升序序列建立平衡二叉搜索树的过程中需要做到 不重不漏 ,故边界处理需要异常小心,不能再套用 start + 1 < end 的模板了。

复杂度分析

递归调用 middleNode 方法时每个 key 被访问一次,故时间复杂度可近似认为是 O(n)O(n)O(n).

Reference

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文