Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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 按顺序N创建最大树_Algorithm_Tree - Fatal编程技术网

Algorithm 按顺序N创建最大树

Algorithm 按顺序N创建最大树,algorithm,tree,Algorithm,Tree,设A为n个不同整数的数组。设A的最大元素的指数为m。将A上的最大树定义为A条目的二叉树,其中根包含A的最大元素,左侧子项是A[0:m-1]上的最大树,右侧子项是A[m+1:n-1]上的最大树。设计了一个O(n)算法来构建max树 在我创建一个虚拟示例的情况下,结果表明给定的数组是max树的有序遍历,对于子树根的给定条件,它们应该是最大的 从理论上讲,在O(n)时间内进行排序似乎是不可能的,因为目前世界上还没有能够在O(n)时间内对条目进行排序的排序算法。任何一种经过调整的逻辑都可以建立在排序后的

A为n个不同整数的数组。设A的最大元素的指数为m。将A上的最大树定义为A条目的二叉树,其中根包含A的最大元素,左侧子项是A[0:m-1]上的最大树,右侧子项是A[m+1:n-1]上的最大树。设计了一个O(n)算法来构建max树


在我创建一个虚拟示例的情况下,结果表明给定的数组是max树的有序遍历,对于子树根的给定条件,它们应该是最大的

从理论上讲,在O(n)时间内进行排序似乎是不可能的,因为目前世界上还没有能够在O(n)时间内对条目进行排序的排序算法。任何一种经过调整的逻辑都可以建立在排序后的条目上,只需要建立树

可以使用更糟糕的情况O(n2)执行正常的递归实现。我在编程面试书的元素中看到了同样的问题,他们并没有提供任何解决方案。也可能是打字错误

递归逻辑

CreateTree(start, end)
if start > end return null
Find index in array between start and end inclusive which contain max value
Create Node with index value
Node.left = CreateTree(start, index - 1);
Node.right = CreateTree(index + 1, end);

确实有可能在O(n)时间内完成。我还附加了测试用例,将我的解决方案与参考O(n logn)解决方案进行比较。要解决这个问题:

以下是几点观察:

  • 所提供的数组是相关树的有序遍历
  • 树具有max heap属性,即节点的祖先值不能小于自身值
  • 方法: 我们将从开始到结束遍历输入数组,并维护一个包含值递减的节点(从下到上)的堆栈。 该堆栈将在顶部包含最近构造的节点,在底部包含具有最大值(根)的节点

    当我们在阵列中移动时:

  • 如果堆栈为空,则将此节点推送到堆栈上
  • 如果堆栈不是空的,并且包含一些值小于当前值的节点,则这些值中最大的将是当前节点的左子节点。不断弹出值,直到堆栈为空或堆栈顶部包含值>当前值。这是根据观察结果#1和#2得出的
  • 当前节点可能是堆栈顶部节点的右子节点。我们可以假设这一点,直到我们看到一个更大的值
  • 由于每个节点只扫描一次并推送到堆栈上,因此这是一个O(n)时间解决方案

    这是代码。main函数创建一个10000个数字的随机数组,并使用上面的O(n)算法和一个朴素的O(n logn)解决方案构造max树。我这样做了1000次,并断言这两棵树是相等的

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <limits>
    #include <cassert>
    #include <stack>
    #include <limits>
    
    using namespace std;
    
    struct Node {
      int data;
      Node* left, *right;
    };
    
    /******************** Solution Begin ***************************/
    Node* Construct(const vector<int>& array) {
      stack<Node*> S;
    
      for (auto&& x : array) {
        Node* node = new Node{x, nullptr, nullptr};
    
        while (!S.empty() && (S.top()->data < x)) {
          node->left = S.top();
          S.pop();
        }
    
        if (!S.empty()) {
          S.top()->right = node;
        }
        S.emplace(node);
      }
    
      Node* last_popped = nullptr;
      while (!S.empty()) {
        last_popped = S.top();
        S.pop();
      }
    
      return last_popped;
    }
    
    /******************** Solution End ***************************/
    
    Node* SlowConstructHelper(const vector<int>& array, int start, int end) {
      if (start > end) return 0;
    
      int m = start;
      for (int i = start + 1; i <= end; i++) {
        if (array[i] > array[m]) m = i;
      }
    
      Node* root = new Node;
      root->data = array[m];
      root->left = SlowConstructHelper(array, start, m - 1);
      root->right = SlowConstructHelper(array, m + 1, end);
      return root;
    }
    
    Node* SlowConstruct(const vector<int>& array) {
      return SlowConstructHelper(array, 0, array.size() - 1);
    }
    
    bool IsEqualTree(Node* tree1, Node* tree2) {
      if ((!tree1) && (!tree2)) return true;
    
      if ((!tree1) || (!tree2)) return false;
    
      return (tree1->data == tree2->data) &&
             IsEqualTree(tree1->left, tree2->left) &&
             IsEqualTree(tree1->right, tree2->right);
    }
    
    int main() {
      const int kNumRuns = 1000;
      const int kArraySize = 10000;
    
      for (int run = 0; run < kNumRuns; run++) {
        vector<int> array(kArraySize);
        for (int i = 0; i < kArraySize; i++) array[i] = i;  // Uniqueness guaranteed
    
        random_shuffle(array.begin(), array.end());
    
        Node* root1 = Construct(array);
        Node* root2 = SlowConstruct(array);
        assert(IsEqualTree(root1, root2));
      }
      return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    结构节点{
    int数据;
    节点*左,*右;
    };
    /********************解决方案开始***************************/
    节点*构造(常量向量和数组){
    堆栈S;
    用于(自动和x:array){
    Node*Node=新节点{x,nullptr,nullptr};
    而(!S.empty()&&(S.top()->数据左=S.top();
    S.pop();
    }
    如果(!S.empty()){
    S.top()->right=节点;
    }
    S.emplace(节点);
    }
    Node*last_popped=nullptr;
    而(!S.empty()){
    最后一次弹出=S.top();
    S.pop();
    }
    返回上次弹出的窗口;
    }
    /********************溶液端***************************/
    节点*SLOWCONSTRUCHTELPER(常量向量和数组、整数开始、整数结束){
    如果(开始>结束)返回0;
    int m=开始;
    对于(int i=start+1;i数组[m])m=i;
    }
    Node*root=新节点;
    根->数据=数组[m];
    root->left=SlowConstructHelper(数组,开始,m-1);
    根->右=慢速构造器(数组,m+1,结束);
    返回根;
    }
    节点*SlowConstruct(常量向量和数组){
    返回SlowConstructHelper(数组,0,array.size()-1);
    }
    布尔IsEqualTree(节点*tree1,节点*tree2){
    if((!tree1)&(!tree2))返回true;
    如果(!tree1)|(!tree2))返回false;
    返回(tree1->data==tree2->data)&&
    IsEqualTree(树1->左,树2->左)&&
    IsEqualTree(树1->右侧,树2->右侧);
    }
    int main(){
    常数int kNumRuns=1000;
    常量int kArraySize=10000;
    对于(int run=0;run

    编辑:早期版本声称树是最大堆。将其更正为“最大堆属性”。

    这看起来像家庭作业;请先让我们看看你自己的想法。我早就离开学校了。所以没有家庭作业的压力。我仍在试图找出如何实现O(n)顺序。我们有两个分区。我们必须递归地在两个分区上构建max树。但是进一步的分区需要找到每个分区的最大值。每次扫描一次。如果我们知道如何存储未来潜在分区元素的索引,那么我们就完成了。但到目前为止,我们仍在想办法。请解释为什么输入应该是输入的最大树的有序遍历。它还会产生线性时间排序算法吗?对于每个节点,决定是先打印左子树还是右子树,然后打印节点本身,就像某种修改的postorder?输入是对输出最大树的按序遍历。我错过什么了吗?左子树后跟根,根是最大值,后跟右子树。这对两个子树都适用。使用堆栈的方法很好,谢谢。注意:树不是最大堆,因为堆是一个完整的二叉树,而这个问题中的树可能不完整。