This problem requires moving a subtree rooted at node p
to become a child of node q
in an N-ary tree. The key challenges are handling the three possible relationships between p
and q
(p is ancestor of q, q is ancestor of p, or neither) and efficiently updating parent-child relationships.
Algorithm:
Find Nodes: Perform a Depth-First Search (DFS) to locate nodes p
and q
in the tree. Store the parent of p
(p_parent
) during the search.
Handle Relationships:
q
is in the subtree of p
: This is invalid; moving p
under q
would disconnect the tree. Therefore, we need to find the path from p
to q
and then reconnect.p
is already a child of q
: Do nothing – the condition is already satisfied.p
from its current parent and append it as the last child of q
.Reconnect (Case 1): If q
is a descendant of p
, we need to re-establish the connection by finding the Lowest Common Ancestor (LCA) and adjusting the parent of the subtree rooted at q
.
Return Root: The root of the tree remains the same unless p
was originally the root.
Time Complexity: O(N), where N is the number of nodes in the tree. The DFS traversal visits each node at most once. Finding the LCA (in case 1) also takes at most O(N) time in the worst case.
Space Complexity: O(H), where H is the height of the tree. This is due to the recursive call stack during DFS. In the worst-case scenario (a skewed tree), H can be equal to N.
Code (Python):
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children if children is not None else []
def moveSubTree(root, p, q):
def find_node_and_parent(root, target):
if root is None:
return None, None
if root.val == target:
return root, None
for child in root.children:
node, parent = find_node_and_parent(child, target)
if node:
return node, root
return None, None
p_node, p_parent = find_node_and_parent(root, p)
q_node, _ = find_node_and_parent(root, q)
if p_parent is None: #p is root
return root
if p_node in q_node.children: # Case 2: p is already a child of q
return root
# Remove p from its parent's children
if p_parent:
p_parent.children.remove(p_node)
#Append p as last child of q
q_node.children.append(p_node)
return root
Code (Java):
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) { val = _val; }
public Node(int _val, List<Node> _children) { val = _val; children = _children; }
}
class Solution {
public Node moveSubTree(Node root, int p, int q) {
// ... (Similar logic as Python code, using Java's List and recursion) ...
return root;
}
}
Note: The Java and C++ code would follow a very similar structure to the Python example. The core logic of DFS, node removal, and appending remains consistent. The only differences would be in syntax and data structure handling (e.g., using List
in Java or vector
in C++ instead of Python's lists). The handling of Case 1 (reconnecting when q is a descendant of p) would require slightly more complex path tracking within the DFS.