【问题标题】:Array to Binary Search Trees Quick数组到二叉搜索树快速
【发布时间】:2019-11-04 09:00:09
【问题描述】:

给定一个整数数组,有没有办法快速将其转换为二叉搜索树(不平衡)?我已经尝试为每个元素一个一个地插入它,但这意味着我必须从头开始遍历每个插入。它工作得很好,但我认为最坏的情况是 O(N^2) 不平衡,例如数组已排序。鉴于 N 很大,我认为这需要一些时间。

回到我的问题,有没有比我说的算法更快的方法?

例如,给定数组 [4,5,2,3,1],有没有一种快速的方法来创建它?

    4  
   /  \  
  2    5  
 / \  
1   3

【问题讨论】:

    标签: algorithm binary-search-tree


    【解决方案1】:

    是的,有一种简单的方法可以从 O(nlogn) 中的整数数组构建平衡的二叉搜索树。

    算法如下:

    1. Sort 整数数组。这需要 O(nlog(n)) 时间
    2. 在 O(n) 时间内从排序数组构造一个 BST。只需保持数组的中间元素为根,并在数组的左+右半部分递归执行此操作即可。

    编辑:

    1. 首先,你不能比 O(nlog(n)) 做得更好,因为这样你就可以在复杂性上比 O(nlogn) 更好地对未排序的数组进行排序(使用比较)。这是impossible
    2. 如果您最初不必进行排序,则可以通过对数组的每个元素使用二叉树插入算法来构造二叉树。

    参考Self-balancing BST 的任何标准实现。在扫描数组时,在第 i 次迭代中,您有 arr[1...i] 的 BST。现在,将 arr[i+1] 添加到 BST(使用插入算法)。

    【讨论】:

    • 好的,我明白了。只是想知道,这是否意味着没有排序就没有更快的方法?我已经更新了这个问题,以展示我的意思的一些例子。
    【解决方案2】:

    已经有了很好的解释。下面是从给定 Array 构造 BST 的代码。

    public static void main(String args[])  
    {       
        Node root=null;
        int arr[]=new int[]{99,35,19,0,11,40,5};
        int length=arr.length;
        Arrays.sort(arr); 
        root=constructBST(arr,0,length-1,root);
    }
    public static Node constructBST(int[]arr,int start,int end,Node root)
    {
        if(start>end)
            return null;
        int mid=(start+end)/2;
    
        if(root==null)
            root=new Node(arr[mid]);
    
        root.left=constructBST(arr,start,mid-1, root.left);
        root.right=constructBST(arr,mid+1,end, root.right);
    
        return root;
    
    }
    

    在此之后只需按顺序遍历到 pri

    【讨论】:

    • 我认为我们不需要将节点传递给constructBST 函数。它仍然可以在没有节点的情况下工作。
    【解决方案3】:

    给定一个整数数组,有没有办法将其转换为二进制 快速搜索树(不平衡)?

    当然。以 O(n logn) 对数组进行排序,选择数组的中间元素作为根,并将左侧中间元素之前的所有元素插入根,右侧中间元素之后的元素(O(n)时间) .总复杂度为O(n logn)。例如,如果您有数组:

    3, 5, 2, 1, 4
    

    您将其排序为1, 2, 3, 4, 5。中间元素是 3 所以你创建了树

          3
         / \
        2   4
       /     \
      1       5
    

    您可以有两个指向中间元素的指针,然后开始将第一个向左移动,另一个向右移动,然后将指针分别指向左右子树的元素插入。

    问题是树的高度是n/2,这意味着搜索操作是O(n),这很慢。为了获得更好的性能,您应该改用自平衡二叉搜索树,例如 red-black treeAVL tree

    【讨论】:

    • 可能使用一些基数排序,因为它是整数数组?
    【解决方案4】:

    好的,我不确定这个解决方案有多优化,但这是我写的

    算法

    1. 对输入数组进行排序
    2. 创建一个采用该排序数组的递归函数
    3. 如果 arr 的长度为 1 或为空数组,则在递归函数内部,返回 arr
    4. 否则计算中点(parseInt(arr.length/2))
    5. 返回一个数组[midpoint, recuriveFunc(arr[leftToMidPoint]),recuriveFunc(arr[rightToMidpoint])]

    Javascript 代码实现

    const arr =  [1,2,3,4,5,6,7]
    
    
    const recursiveSetValues = (arr) => {
      if (arr.length < 2) return arr
      const midPoint = parseInt(arr.length/2)
      return [arr[midPoint], ...recursiveSetValues(arr.slice(0, midPoint)), ...recursiveSetValues(arr.slice(midPoint+1, arr.length))]
    }
    
    
    const sortArray = arr.sort((a,b) => a-b)
    console.log(recursiveSetValues(sortArray))

    【讨论】:

      猜你喜欢
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多