查找给定树中每个子树的 MEX
给定一棵由从0到N – 1编号的N个节点组成的通用树,该节点以节点0为根,以及一个数组val[] ,使得每个节点的值由val[i]表示,每个节点的任务是找到其子树的MEX值。
The MEX value of node V is defined as the smallest missing positive number in a tree rooted at node V.
例子:
Input: N = 6, edges = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {3, 5}}, val[] = {4, 3, 5, 1, 0, 2}
Output: [6, 0, 0, 3, 1, 0]
Explanation:
0(4)
/ \
1(3) 3(1)
/ / \
2(5) 4(0) 5(2)
In the subtrees of:
Node 0: All the values in range [0, 5] are present, hence the smallest non-negative value not present is 6.
Node 1: The smallest non-negative value not present in subtree of node 1 is 0.
Node 2: The smallest non-negative value not present in subtree of node 2 absent is 0.
Node 3: All the values in range [0, 2] are present, hence the smallest non-negative value not present in subtree of node 3 is 3.
Node 4: The smallest non-negative value not present in subtree of node 4 is 1.
Node 5: The smallest non-negative value not present in subtree of node 5 is 0.
方法:给定问题可以使用给定树上的 DFS 遍历来解决,并执行二进制搜索以在每个节点子树中找到丢失的最小正整数。请按照以下步骤解决问题:
- 初始化一个数组,比如sol[]来存储每个节点的 MEX。
- 从节点0执行 DFS 遍历并执行以下步骤:
- 为向量中的每个节点存储 DFS 期间的所有节点。
- 为递归调用中的每个节点按排序顺序合并两个向量。
- 对排序列表应用二分查找,找到排序数组中不存在的最小非负整数值,并将当前子树的MEX值存储在数组sol[]中。
- 完成上述步骤后,打印存储在数组sol[]中的值作为结果。
下面是上述方法的实现:
C++14
// C++ program for the above approach
#include
using namespace std;
// Stores the edges of the tree
vector > edges;
// Function to add edges
void add_edge(int x, int y)
{
edges.push_back({ x, y });
}
// Function to merge two sorted vectors
vector merge(vector& a,
vector& b)
{
// To store the result
vector res;
int i = 0, j = 0;
int n = a.size(), m = b.size();
// Iterating both vectors
while (i < n && j < m) {
if (a[i] < b[j])
res.push_back(a[i++]);
else if (b[j] < a[i])
res.push_back(b[j++]);
}
// Pushing remaining elements of
// vector a
while (i < n)
res.push_back(a[i++]);
// Pushing remaining elements of
// vector b
while (j < m)
res.push_back(b[j++]);
return res;
}
// Function to perform the DFS Traversal
// that returns the subtree of node
// in sorted manner
vector help(vector tree[], int x,
int p, vector& c,
vector& sol)
{
vector res;
res.push_back(c[x]);
// Iterate the childrens
for (auto i : tree[x]) {
// All values of subtree
// i in sorted manner
if (i != p) {
vector tmp
= help(tree, i, x, c, sol);
res = merge(res, tmp);
}
}
int l = 0, r = res.size() - 1;
int ans = res.size();
// Binary search to find MEX
while (l <= r) {
// Find the mid
int mid = (l + r) / 2;
// Update the ranges
if (res[mid] > mid)
r = mid - 1;
else {
ans = mid + 1;
l = mid + 1;
}
}
if (res[0] != 0)
ans = 0;
// Update the MEX for the current
// tree node
sol[x] = ans;
return res;
}
// Function to find MEX of each
// subtree of tree
void solve(int A, vector C)
{
int n = A;
vector tree[n + 1];
for (auto i : edges) {
tree[i[0]].push_back(i[1]);
tree[i[1]].push_back(i[0]);
}
vector sol(n, 0);
// Function Call
help(tree, 0, -1, C, sol);
// Print the ans for each nodes
for (auto i : sol)
cout << i << " ";
}
// Driver Code
int main()
{
int N = 6;
add_edge(0, 1);
add_edge(1, 2);
add_edge(0, 3);
add_edge(3, 4);
add_edge(3, 5);
vector val = { 4, 3, 5, 1, 0, 2 };
solve(N, val);
return 0;
}
Javascript
6 0 0 3 1 0
时间复杂度: O(N*(N + log N))
辅助空间: O(N)