# Definition for a QuadTree node.
class Node:
def __init__(self, val, isLeaf, topLeft=None, topRight=None, bottomLeft=None, bottomRight=None):
self.val = val
self.isLeaf = isLeaf
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
class Solution:
def intersect(self, quadTree1: 'Node', quadTree2: 'Node') -> 'Node':
if quadTree1.isLeaf:
if quadTree1.val:
return Node(True, True)
else:
return quadTree2
if quadTree2.isLeaf:
if quadTree2.val:
return Node(True, True)
else:
return quadTree1
tl = self.intersect(quadTree1.topLeft, quadTree2.topLeft)
tr = self.intersect(quadTree1.topRight, quadTree2.topRight)
bl = self.intersect(quadTree1.bottomLeft, quadTree2.bottomLeft)
br = self.intersect(quadTree1.bottomRight, quadTree2.bottomRight)
# If all children are leaves and have the same value, merge them
if tl.isLeaf and tr.isLeaf and bl.isLeaf and br.isLeaf and \
tl.val == tr.val == bl.val == br.val:
return Node(tl.val, True)
return Node(False, False, tl, tr, bl, br)
/*
// Definition for a QuadTree node.
class Node {
public:
bool val;
bool isLeaf;
Node* topLeft;
Node* topRight;
Node* bottomLeft;
Node* bottomRight;
Node() : val(false), isLeaf(false), topLeft(NULL), topRight(NULL), bottomLeft(NULL), bottomRight(NULL) {}
Node(bool _val, bool _isLeaf) : val(_val), isLeaf(_isLeaf), topLeft(NULL), topRight(NULL), bottomLeft(NULL), bottomRight(NULL) {}
Node(bool _val, bool _isLeaf, Node* _topLeft, Node* _topRight, Node* _bottomLeft, Node* _bottomRight)
: val(_val), isLeaf(_isLeaf), topLeft(_topLeft), topRight(_topRight), bottomLeft(_bottomLeft), bottomRight(_bottomRight) {}
};
*/
class Solution {
public:
Node* intersect(Node* quadTree1, Node* quadTree2) {
if (quadTree1->isLeaf) {
if (quadTree1->val) return new Node(true, true);
else return quadTree2;
}
if (quadTree2->isLeaf) {
if (quadTree2->val) return new Node(true, true);
else return quadTree1;
}
Node* tl = intersect(quadTree1->topLeft, quadTree2->topLeft);
Node* tr = intersect(quadTree1->topRight, quadTree2->topRight);
Node* bl = intersect(quadTree1->bottomLeft, quadTree2->bottomLeft);
Node* br = intersect(quadTree1->bottomRight, quadTree2->bottomRight);
if (tl->isLeaf && tr->isLeaf && bl->isLeaf && br->isLeaf &&
tl->val == tr->val && tl->val == bl->val && tl->val == br->val) {
return new Node(tl->val, true);
}
return new Node(false, false, tl, tr, bl, br);
}
};
/*
// Definition for a QuadTree node.
class Node {
public boolean val;
public boolean isLeaf;
public Node topLeft;
public Node topRight;
public Node bottomLeft;
public Node bottomRight;
public Node() {}
public Node(boolean val, boolean isLeaf) {
this.val = val;
this.isLeaf = isLeaf;
}
public Node(boolean val, boolean isLeaf, Node topLeft, Node topRight, Node bottomLeft, Node bottomRight) {
this.val = val;
this.isLeaf = isLeaf;
this.topLeft = topLeft;
this.topRight = topRight;
this.bottomLeft = bottomLeft;
this.bottomRight = bottomRight;
}
};
*/
class Solution {
public Node intersect(Node quadTree1, Node quadTree2) {
if (quadTree1.isLeaf) {
if (quadTree1.val) return new Node(true, true);
else return quadTree2;
}
if (quadTree2.isLeaf) {
if (quadTree2.val) return new Node(true, true);
else return quadTree1;
}
Node tl = intersect(quadTree1.topLeft, quadTree2.topLeft);
Node tr = intersect(quadTree1.topRight, quadTree2.topRight);
Node bl = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
Node br = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
if (tl.isLeaf && tr.isLeaf && bl.isLeaf && br.isLeaf &&
tl.val == tr.val && tl.val == bl.val && tl.val == br.val) {
return new Node(tl.val, true);
}
return new Node(false, false, tl, tr, bl, br);
}
}
/*
class Node {
constructor(val, isLeaf, topLeft, topRight, bottomLeft, bottomRight) {
this.val = val;
this.isLeaf = isLeaf;
this.topLeft = topLeft;
this.topRight = topRight;
this.bottomLeft = bottomLeft;
this.bottomRight = bottomRight;
}
}
*/
var intersect = function(quadTree1, quadTree2) {
if (quadTree1.isLeaf) {
if (quadTree1.val) return new Node(true, true);
else return quadTree2;
}
if (quadTree2.isLeaf) {
if (quadTree2.val) return new Node(true, true);
else return quadTree1;
}
let tl = intersect(quadTree1.topLeft, quadTree2.topLeft);
let tr = intersect(quadTree1.topRight, quadTree2.topRight);
let bl = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
let br = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
if (tl.isLeaf && tr.isLeaf && bl.isLeaf && br.isLeaf &&
tl.val === tr.val && tl.val === bl.val && tl.val === br.val) {
return new Node(tl.val, true);
}
return new Node(false, false, tl, tr, bl, br);
};
You are given two binary grids, each represented as a quad-tree. Each quad-tree node contains:
val
: a boolean indicating the value of the region (True for 1, False for 0)isLeaf
: a boolean indicating whether the node is a leaf (i.e., represents a uniform region)topLeft
, topRight
, bottomLeft
, bottomRight
: pointers to the four child nodes (if not a leaf)The output must also be a quad-tree in the same format. You may merge nodes if all four children are leaves and have the same value. The input quad-trees are valid and represent grids of the same size.
At first glance, this problem might seem to require converting the quad-trees back to grids, performing the OR operation cell by cell, and then constructing a new quad-tree. However, this would be inefficient and unnecessary. Instead, we can take advantage of the recursive, hierarchical nature of quad-trees.
The key insight is that the logical OR operation can be performed directly on the quad-tree nodes:
Let's walk through a simple example:
Suppose quadTree1
is a leaf node representing a 2x2 region of all 0s (val=False, isLeaf=True
).
quadTree2
is an internal node with four children:
topLeft
: leaf, value 1topRight
: leaf, value 0bottomLeft
: leaf, value 0bottomRight
: leaf, value 1quadTree1
is a leaf with value 0, return quadTree2
as the result (since OR with 0 leaves the other unchanged).quadTree2
.
Now, if quadTree1
were a leaf with value 1, the result would be a single leaf node with value 1, since OR with 1 is always 1.
For more complex trees, the recursion would continue, comparing and combining corresponding children at each level.
The key to solving the Logical OR of Two Binary Grids Represented as Quad-Trees is to use the recursive structure of quad-trees to perform the operation efficiently. By handling leaf nodes as base cases and recursively combining internal nodes, we avoid unnecessary expansion to full grids and keep the tree compact by merging uniform regions. This approach is both elegant and efficient, making optimal use of the quad-tree's properties.