Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何使用平衡二叉树来解决这个难题?_Algorithm_Tree_Binary Tree_Binary Search Tree_Nodes - Fatal编程技术网

Algorithm 如何使用平衡二叉树来解决这个难题?

Algorithm 如何使用平衡二叉树来解决这个难题?,algorithm,tree,binary-tree,binary-search-tree,nodes,Algorithm,Tree,Binary Tree,Binary Search Tree,Nodes,这是在线挑战赛(不是现场比赛)。我不需要有人帮我解决问题,只要朝着正确的方向前进。努力学习 每个节点都有一个唯一的ID,没有两个人有相同的薪水。例如,一个人的薪水是70美元,七个人的薪水是30美元。树结构表示谁监督谁。问题是谁的下属薪水第k低 例如,我选择person#2。谁在下属中排名第二#2的下属是3、4、7、8。第二低工资为50美元,属于8人 有许多查询,因此结构必须是高效的 我考虑了这个问题,研究了数据结构。二叉树似乎是个好主意,但我需要帮助 例如,我认为理想的结构是这样的,对于pers

这是在线挑战赛(不是现场比赛)。我不需要有人帮我解决问题,只要朝着正确的方向前进。努力学习

每个节点都有一个唯一的ID,没有两个人有相同的薪水。例如,一个人的薪水是70美元,七个人的薪水是30美元。树结构表示谁监督谁。问题是谁的下属薪水第k低

例如,我选择person#2。谁在下属中排名第二#2的下属是3、4、7、8。第二低工资为50美元,属于8人

有许多查询,因此结构必须是高效的

我考虑了这个问题,研究了数据结构。二叉树似乎是个好主意,但我需要帮助

例如,我认为理想的结构是这样的,对于person#2:

每个子节点都是#2的下级,每个左分支的薪资都低于右分支。如果我在每个节点上存储多少子节点,我可以得到第k个最低值

例如:从#2,左分支1节点,右分支3节点。所以倒数第二个-1意味着我现在想要右分支中倒数第一个

移动到#3,第一个最低点到#8,50美元是正确的

我的问题:

  • 我所描述的这种方法是好的吗?这是一种有效的方法吗

  • 我很难想出如何建造这种树。我想我可以递归地创建它们。但很难弄清楚如何让所有的孩子都按工资排序成新的树。需要一些轻的帮助


  • 这里有一个可能的解决方案。对于每个节点,我们将构造一个包含该节点所有子节点值的数组,并将其按顺序排序。我们正在寻找的结果是这种形式的词典

        2(40)  
         / \      
        /   \      
     7(30)  3(60)
             / \
            /   \
         8(50)  4(80)
    
    一旦有了它,要查询任何节点的第i个最低工资,只需获取数组的第i个元素。执行所有查询的总时间为O(q),其中q是查询数

    我们如何构造这个?假设您有一个指向根节点的指针,您可以递归地为每个子节点构造排序后的薪资。将这些值存储在结果中。制作每个孩子的数组的副本,并将每个孩子的工资插入到孩子复制的数组中。使用二进制搜索查找位置,因为每个数组都已排序。现在有了k个排序数组,您可以合并它们以获得一个排序数组。如果要合并两个阵列,可以在线性时间内完成。只需循环,每次拾取数组中较小的第一个元素

    对于每个节点有2个子节点的情况,合并这两个子节点的数组是O(n)tine。因为我们使用二进制搜索,所以将每个节点的工资插入到其对应的数组中是O(log(n))。复制子数组是O(n),并且有n个节点,因此预处理的总时间是O(n^2)

    总运行时间为O(n^2+q)


    如果我们不能假设每个节点最多有2个子节点,该怎么办?然后要合并数组,请使用算法。这在O(nlog(k))中运行,其中k是要合并的数组数,因为每个元素从堆中弹出一次,当有k个数组时,调整堆的大小需要O(log(k))
    k问题有两部分:首先,找到指定的人,然后找到第k个下属。
    由于树不是按id排序的,要按id查找指定的perspn,需要遍历整个树,直到找到指定的id为止。为了加快这部分的速度,我们可以构建一个hash映射,它允许我们在O(1)时间内通过id找到person节点,并且需要O(n)空间和设置时间。
    
    然后,为了找到第k个最低工资的下属,我们需要搜索子树。因为它不是按工资排序的,所以我们必须扫描整个子树,找到第k个最低工资。这可以使用数组或堆(将子树节点放入数组或堆)来完成。第二部分是O(m log k)时间,使用堆来保持最低的k项,其中m是子坐标数,需要O(k)空间。如果m(指定人员的下属人数)和k较小,则这应该是可以接受的。

    这里有一个解决方案,它使用O(n log^2 n+q log n)时间和O(n log^2 n)空间(在后一个计数中不是最好的,但考虑到限制,可能已经足够好了)

    通过以下操作和某种迭代方式实现一个纯函数排序列表(作为一个扩展的二叉搜索树)

    { 1 : [10, 20, 30, 40, 60 80],
      2 : [30, 50, 60, 80] 
      ...
    }
    
    在这些操作之上,实现一个操作

    EmptyList() -> returns the empty list
    Insert(list, key) -> returns the list where |key| has been inserted into |list|
    Length(list) -> returns the length of the list
    Get(list, k) -> returns the element at index |k| in |list|
    
    通过将较短列表中的元素插入较长列表中

    现在做一件显而易见的事情:从叶子到根遍历员工层次结构,将每个员工的有序列表设置为其下属列表的适当合并,并回答查询

    分析(草图) 每个查询都需要O(logn)时间。分析中有趣的部分与预处理有关

    预处理的成本主要是调用
    Insert()
    ,特别是从
    Merge()
    ,因为还有n个其他插入。每次插入都需要O(logn)时间和O(logn)空间(以字为单位)


    使预处理不至于是二次的是隐式的。每次我们合并两个列表时,随后两个列表都不会合并。由于较短的列表插入较长的列表,因此每次将键插入列表时,该列表的长度至少是先前插入该键的列表的两倍。因此,每个键最多都是lg n插入的主题,这足以建立O(n log n)个插入的总体范围,从而确定所声明的资源范围。

    您的方法的问题是,您弄乱了依赖关系结构。例如,在以
    2
    为根的树中,如果我随后查询有关
    4
    的内容,您的树会说
    4
    没有子项,这是错误的-
    7
    8
    应该是
    4
    的子项。而不是在薪资排序方面。这就是第二棵树的意思
    EmptyList() -> returns the empty list
    Insert(list, key) -> returns the list where |key| has been inserted into |list|
    Length(list) -> returns the length of the list
    Get(list, k) -> returns the element at index |k| in |list|
    
    Merge(list1, list2) -> returns the union of |list1| and |list2|