将已排序的双向链表转换为 BST

发布于 2024-12-11 10:50:28 字数 342 浏览 4 评论 0原文

如何将已排序的双向链表转换为平衡二叉搜索树。

我正在考虑以与将数组转换为平衡 BST 相同的方式进行此操作。 找到中心,然后递归地转换DLL的左侧部分和右侧部分。 例如,

1 2 3 4 5 => 1 2 (3) 4 5 =>

     3
   /   \
  2     4
 /       \
1         5

这导致递归 T(n) = 2T(n/2) + O(n)。 O(n) 用于寻找中心。 因此时间复杂度为 O(nlogn)。 我想知道是否有一种算法可以在 O(n) 内完成此操作。

How can a sorted doubly linked list be converted to a balanced binary search tree.

I was thinking of doing this the same way as converting an array to a balanced BST.
Find the centre and then recursively convert the left part and the right part of the DLL.
For example,

1 2 3 4 5 => 1 2 (3) 4 5
=>

     3
   /   \
  2     4
 /       \
1         5

This is leads to the recurrence T(n) = 2T(n/2) + O(n). O(n) is for finding the centre.
The time complexity is therefore O(nlogn).
I was wondering if there is an algorithm that does this in O(n).

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

呆橘 2024-12-18 10:50:28

是的,有 O(n) 解。请注意,中序遍历 BST 是以所需的顺序迭代元素,因此只需对大小为 n 的初始空树进行中序遍历,并用列表中的元素填充它即可。 [在遍历中插入到树中的第 i 个元素是列表中的第 i 个元素]。

在答案的末尾,我添加了如何在 O(n) 中创建空平衡树。

伪代码:[假设 |list| == |tree|]

global current <- null
fillTree(tree,list):
  current <- list.head
  fillTree(tree)
fillTree(tree):
  if tree == null:
     return
  fillTree(tree.left)
  //in-order traversal: we set the value after setting left, and before calling right
  tree.val <- current.val
  current <- current.next
  fillTree(tree.right)

复杂度很小 O(n),因为树的每个顶点都只有一次迭代,并且每次迭代都是 O(1)。

编辑:

您可以通过简单地构建一个空的创建一个空的平衡树完整的树(*),它是平衡的,构建它的时间复杂度为 O(n)。

(*)完全二叉树是其中每个级别(可能除了最后一个级别)都被完全填充的二叉树。

Yes there is O(n) solution. Note that an in-order traversal on a BST, is iterating the elements in the desired order, so just do an inorder traversal on an initially empty tree of size n, and fill it with elements in the list. [The i'th element you insert to the tree in your traversal, is the i'th element in the list].

At the end of the answer I added how to create an empty balanced tree in O(n).

pseudocode: [assuming |list| == |tree|]

global current <- null
fillTree(tree,list):
  current <- list.head
  fillTree(tree)
fillTree(tree):
  if tree == null:
     return
  fillTree(tree.left)
  //in-order traversal: we set the value after setting left, and before calling right
  tree.val <- current.val
  current <- current.next
  fillTree(tree.right)

Complexity is trivially O(n), since there is excactly one iteration for each vertex of the tree, and each iteration is O(1).

EDIT:

You can create an empty balanced tree, by simply building an empty complete tree(*), it is balanced and building it is O(n).

(*)A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled.

那支青花 2024-12-18 10:50:28

晚了将近4年。但这是我的功能解决方案。以下是我在 haskell 中的代码,复杂度也是 O(n)

import Data.List hiding (insert)

data Color = R | B deriving Show
data RBTree a = RBEmpty | RBTree { color :: Color
                                 , ltree :: RBTree a
                                 , nod   :: a
                                 , rtree :: RBTree a } deriving Show

fromOrdList ::  Ord e => [e] -> RBTree e
fromOrdList [] = empty
fromOrdList lst = 
    let (res, _) = _fol lst $ length lst
    in res
    where _fol :: (Ord e, Integral a) => [e] -> a -> (RBTree e, Maybe (e, [e]))
          _fol l 0            = (empty, uncons l)
          _fol (h:l) 1        = (RBTree B empty h empty, uncons l)
          _fol (h1:h2:l) 2    = (RBTree B (RBTree R empty h1 empty) h2 empty, uncons l)
          _fol (h1:h2:h3:l) 3 = (RBTree B (RBTree R empty h1 empty) h2 (RBTree R empty h3 empty), uncons l)
          _fol l n            =
            let mid                  = n `div` 2
                (ltr, Just (rt, tl)) = _fol l mid
                (rtr, mayremain)     = _fol tl (n - 1 - mid)
in (RBTree B ltr rt rtr, mayremain)

这实际上是我个人实践的一部分:https://github.com/HuStmpHrrr/PFDSPractise/blob/master/src/Tree/RBTree.hs#L97

almost 4 years late. but here comes my functional solution. following is my code in haskell, complexity is also O(n):

import Data.List hiding (insert)

data Color = R | B deriving Show
data RBTree a = RBEmpty | RBTree { color :: Color
                                 , ltree :: RBTree a
                                 , nod   :: a
                                 , rtree :: RBTree a } deriving Show

fromOrdList ::  Ord e => [e] -> RBTree e
fromOrdList [] = empty
fromOrdList lst = 
    let (res, _) = _fol lst $ length lst
    in res
    where _fol :: (Ord e, Integral a) => [e] -> a -> (RBTree e, Maybe (e, [e]))
          _fol l 0            = (empty, uncons l)
          _fol (h:l) 1        = (RBTree B empty h empty, uncons l)
          _fol (h1:h2:l) 2    = (RBTree B (RBTree R empty h1 empty) h2 empty, uncons l)
          _fol (h1:h2:h3:l) 3 = (RBTree B (RBTree R empty h1 empty) h2 (RBTree R empty h3 empty), uncons l)
          _fol l n            =
            let mid                  = n `div` 2
                (ltr, Just (rt, tl)) = _fol l mid
                (rtr, mayremain)     = _fol tl (n - 1 - mid)
in (RBTree B ltr rt rtr, mayremain)

which is actually a part of my personal practise: https://github.com/HuStmpHrrr/PFDSPractise/blob/master/src/Tree/RBTree.hs#L97

从来不烧饼 2024-12-18 10:50:28

看看我的递归插入实现(c#)。有 T(n) = 2*T(n/2) + O(1)。 O(1) 用于找到中心:(l+r)/2。所以共谋是 O(n)

public class Tree<T>
  {
    public class TreeNode<T>
    {
      public TreeNode<T> Right { get; set; }
      public TreeNode<T> Left { get; set; }
      public T Data { get; set; }
    }

    public Tree()
    {
      Root = new TreeNode<T>();
    }  

    public TreeNode<T> Root { get; set; }

    private void InsertSortedListRec(IList<T> items, TreeNode<T> curNode, int l, int r)
    {
      var mid = (l + r)/2;
      curNode.Data = items[mid];

      if (mid - 1 >= l)
      {
        curNode.Left = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Left, l, mid - 1);
      }

      if (mid + 1 <= r)
      {
        curNode.Right = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Right, mid + 1, r);
      }
  }

    public void InsertSortedList(IList<T> items)
    {
      InsertSortedListRec(items, Root, 0, items.Count - 1);
    }
  }

我假设我们有索引数组(我们可以将链表转换为数组 O(n))

Look at my implementation of recursive insertion (c#). There are T(n) = 2*T(n/2) + O(1). O(1) is for finding the centre: (l+r)/2. So complicity is O(n)

public class Tree<T>
  {
    public class TreeNode<T>
    {
      public TreeNode<T> Right { get; set; }
      public TreeNode<T> Left { get; set; }
      public T Data { get; set; }
    }

    public Tree()
    {
      Root = new TreeNode<T>();
    }  

    public TreeNode<T> Root { get; set; }

    private void InsertSortedListRec(IList<T> items, TreeNode<T> curNode, int l, int r)
    {
      var mid = (l + r)/2;
      curNode.Data = items[mid];

      if (mid - 1 >= l)
      {
        curNode.Left = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Left, l, mid - 1);
      }

      if (mid + 1 <= r)
      {
        curNode.Right = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Right, mid + 1, r);
      }
  }

    public void InsertSortedList(IList<T> items)
    {
      InsertSortedListRec(items, Root, 0, items.Count - 1);
    }
  }

I assume that we have indexed array (we can convert linked list to array O(n))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文