📌  相关文章
📜  查询以在二叉树中的给定范围内查找具有垂直宽度的所有节点的权重总和

📅  最后修改于: 2021-10-27 08:56:54             🧑  作者: Mango

给定一个由N 个节点组成的二叉树,其值在[0, N – 1]范围内根为0 ,一个大小为N的数组wt[] ,其中wt[i]是第i节点的权重和一个二维数组Q [][]{L, R}类型的查询组成,每个查询的任务是找到垂直宽度在[L, R]范围内的所有节点的权重总和。

例子:

朴素方法:解决给定问题的最简单方法是对每个查询在树上执行遍历,然后打印位于给定范围[L, R]内的所有节点的权重总和。

时间复杂度: O(N*Q)
辅助空间: O(1)

高效方法:上述方法也可以通过预先计算每个宽度位置的权重总和并将它们存储在映射M 中,然后找到新创建的数组的前缀总和以在恒定时间内处理查询来优化上述方法。请按照以下步骤解决问题:

  • 在给定的树上执行 DFS 遍历并通过执行以下操作更新所有宽度位置的总和并将它们存储在映射M 中
    • 最初,根的位置pos0
    • 在每次递归调用,通过更新M [POS]更新节点的M中的重量= M [POS] +重量[节点。
    • 通过将pos递减1递归调用其左孩子。
    • 通过将pos递增1递归调用其右孩子。
  • 迭代映射M并将每个键值对更新为先前发生的值的总和。
  • 现在,遍历数组Queries[]并为每个查询[L, R]打印(M[R] – M[L – 1]) 的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Structure of a node
struct Node {
    int data;
    Node* left;
    Node* right;
};
 
// Function to create new node
Node* newNode(int d)
{
    Node* n = new Node;
    n->data = d;
    n->left = NULL;
    n->right = NULL;
    return n;
}
 
// Function to pre-compute the sum of
// weights at each width position
void findwt(Node* root, int wt[],
            map& um,
            int width = 0)
{
    // Base Case
    if (root == NULL) {
        return;
    }
 
    // Update the current width
    // position weight
    um[width] += wt[root->data];
 
    // Recursive Call to its left
    findwt(root->left, wt, um,
           width - 1);
 
    // Recursive Call to its right
    findwt(root->right, wt, um,
           width + 1);
}
 
// Function to find the sum of the
// weights of nodes whose vertical
// widths lies over the range [L, R]
// for Q queries
void solveQueries(int wt[], Node* root,
                  vector > queries)
{
    // Stores the weight sum
    // of each width position
    map um;
 
    // Function Call to fill um
    findwt(root, wt, um);
 
    // Stores the sum of all previous
    // nodes, while traversing Map
    int x = 0;
 
    // Traverse the Map um
    for (auto it = um.begin();
         it != um.end(); it++) {
        x += it->second;
        um[it->first] = x;
    }
 
    // Iterate over all queries
    for (int i = 0;
         i < queries.size(); i++) {
 
        int l = queries[i][0];
        int r = queries[i][1];
 
        // Print the result for the
        // current query [l, r]
        cout << um[r] - um[l - 1]
             << "\n";
    }
}
 
// Driver Code
int main()
{
    int N = 8;
 
    // Given Tree
    Node* root = newNode(1);
    root->left = newNode(3);
    root->left->left = newNode(5);
    root->left->right = newNode(6);
    root->right = newNode(2);
    root->right->right = newNode(4);
    root->right->right->left = newNode(7);
    root->right->right->right = newNode(0);
    int wt[] = { 8, 6, 4, 5, 1, 2, 9, 1 };
    vector > queries{ { -1, 1 },
                                  { -2, -1 },
                                  { 0, 3 } };
 
    solveQueries(wt, root, queries);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG{
   
// Structure of a node
static class Node
{
    int data;
    Node left;
    Node right;
}
 
// Function to create new node
static Node newNode(int d)
{
    Node n = new Node();
    n.data = d;
    n.left = null;
    n.right = null;
    return n;
}
 
// Function to pre-compute the sum of
// weights at each width position
static void findwt(Node root, int wt[],
                   TreeMap um,
                   int width)
{
     
    // Base Case
    if (root == null)
    {
        return;
    }
     
    // Update the current width
    // position weight
    if (um.containsKey(width))
    {
        um.put(width, um.get(width) +
               wt[root.data]);
    }
    else
    {
        um.put(width, wt[root.data]);
    }
 
    // Recursive Call to its left
    findwt(root.left, wt, um,
           width - 1);
 
    // Recursive Call to its right
    findwt(root.right, wt, um,
           width + 1);
}
 
// Function to find the sum of the
// weights of nodes whose vertical
// widths lies over the range [L, R]
// for Q queries
static void solveQueries(int wt[], Node root,
                         int[][] queries)
{
     
    // Stores the weight sum
    // of each width position
    TreeMap um = new TreeMap();
 
    // Function Call to fill um
    findwt(root, wt, um, 0);
 
    // Stores the sum of all previous
    // nodes, while traversing Map
    int x = 0;
 
    // Traverse the Map um
      for(Map.Entry it : um.entrySet())
      {
        x += it.getValue();
          um.put(it.getKey(), x);
    }
 
    // Iterate over all queries
    for(int i = 0; i < queries.length; i++)
    {
        int l = queries[i][0];
        int r = queries[i][1];
 
        // Print the result for the
        // current query [l, r]
          int ans = 0;
          if (um.containsKey(r))
          {
              ans = um.get(r);
        }
           
          if (um.containsKey(l - 1))
          {
              ans -= um.get(l - 1);
        }
        System.out.println(ans);
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 8;
 
    // Given Tree
    Node root = newNode(1);
    root.left = newNode(3);
    root.left.left = newNode(5);
    root.left.right = newNode(6);
    root.right = newNode(2);
    root.right.right = newNode(4);
    root.right.right.left = newNode(7);
    root.right.right.right = newNode(0);
     
    int wt[] = { 8, 6, 4, 5, 1, 2, 9, 1 };
    int queries[][] = { { -1, 1 },
                        { -2, -1 },
                        { 0, 3 } };
 
    solveQueries(wt, root, queries);
}
}
 
// This code is contributed by Dharanendra L V.


输出:
25
7
29

时间复杂度: O(N*log N + Q)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程