Medium

题目描述

二进制矩阵是一个只包含 0 和 1 的矩阵。

给定两个四叉树 quadTree1quadTree2quadTree1 表示一个 n * n 二进制矩阵,quadTree2 表示另一个 n * n 二进制矩阵。

返回一个表示 n * n 二进制矩阵的四叉树,该矩阵是 quadTree1quadTree2 所表示的两个二进制矩阵进行逻辑或运算的结果。

请注意,当 isLeafFalse 时,你可以把 True 或者 False 赋值给节点,两种值都会被判题机制接受。

四叉树是一种树数据结构,其中每个内部节点恰好有四个子节点。此外,每个节点都有两个属性:

  • val:储存叶子结点所代表的区域的值。1 对应 True,0 对应 False
  • isLeaf: 当这个节点是一个叶子结点时为 True,如果它有四个子节点则为 False
class Node {
    public boolean val;
    public boolean isLeaf;
    public Node topLeft;
    public Node topRight;
    public Node bottomLeft;
    public Node bottomRight;
}

我们可以按以下步骤为二维区域构建四叉树:

  1. 如果当前网格的值相同(即,全为 1 或者全为 0),将 isLeaf 设为 True ,将 val 设为网格相应的值,并将四个子节点都设为 Null 然后停止。
  2. 如果当前网格的值不同,将 isLeaf 设为 False, 将 val 设为任意值,然后如下图所示,将当前网格划分为四个子网格。
  3. 使用适当的子网格递归每个子节点。

示例 1:

输入:quadTree1 = [[0,1],[1,1],[1,1],[1,0],[1,0]]
, quadTree2 = [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
输出:[[0,0],[1,1],[1,1],[1,1],[1,0]]
解释:quadTree1 和 quadTree2 如上所示。由它们表示的二进制矩阵也已经给出。
如果我们对这两个二进制矩阵进行按位逻辑或运算,则可以得到下面的二进制矩阵,由结果四叉树表示。
注意,我们展示的二进制矩阵仅仅是为了便于理解,你无需构造二进制矩阵来获得结果四叉树。

示例 2:

输入:quadTree1 = [[1,0]], quadTree2 = [[1,0]]
输出:[[1,0]]
解释:两个数表示的都是大小为 1*1 的矩阵,且值为 false 的四叉树
结果矩阵大小为 1*1,值为 false

提示:

  • quadTree1quadTree2 都是符合题目要求的四叉树,每个都代表一个 n * n 的矩阵。
  • n == 2^x 其中 0 <= x <= 9

解题思路

解题思路

这道题要求对两个四叉树表示的二进制矩阵进行逻辑或运算。我们可以使用递归分治的思想来解决这个问题。

核心思路

逻辑或运算的特点是:0 OR 0 = 00 OR 1 = 11 OR 0 = 11 OR 1 = 1

对于四叉树节点,我们需要考虑以下几种情况:

  1. 两个节点都是叶子节点:直接对它们的值进行逻辑或运算
  2. 其中一个是叶子节点,另一个不是
    • 如果叶子节点的值为 1,则整个区域都是 1,结果是叶子节点值为 1
    • 如果叶子节点的值为 0,则结果取决于另一个非叶子节点
  3. 两个节点都不是叶子节点:需要递归处理四个对应的子节点

优化策略

在递归构建结果树时,我们需要检查是否可以将四个子节点合并为一个叶子节点。如果四个子节点都是叶子节点且值相同,我们可以将它们合并。

算法步骤

  1. 处理基础情况:至少一个节点是叶子节点
  2. 递归处理四个子节点
  3. 检查是否可以合并子节点
  4. 构建并返回结果节点

推荐解法:递归分治法,时间复杂度最优且代码简洁。

代码实现

class Solution {
public:
    Node* intersect(Node* quadTree1, Node* quadTree2) {
        // 如果其中一个节点是叶子节点
        if (quadTree1->isLeaf) {
            // 如果quadTree1是1,则结果是1(1 OR anything = 1)
            return quadTree1->val ? quadTree1 : quadTree2;
        }
        if (quadTree2->isLeaf) {
            // 如果quadTree2是1,则结果是1(anything OR 1 = 1)
            return quadTree2->val ? quadTree2 : quadTree1;
        }
        
        // 两个都不是叶子节点,递归处理四个子节点
        Node* topLeft = intersect(quadTree1->topLeft, quadTree2->topLeft);
        Node* topRight = intersect(quadTree1->topRight, quadTree2->topRight);
        Node* bottomLeft = intersect(quadTree1->bottomLeft, quadTree2->bottomLeft);
        Node* bottomRight = intersect(quadTree1->bottomRight, quadTree2->bottomRight);
        
        // 检查是否可以合并为一个叶子节点
        if (topLeft->isLeaf && topRight->isLeaf && 
            bottomLeft->isLeaf && bottomRight->isLeaf &&
            topLeft->val == topRight->val && 
            topLeft->val == bottomLeft->val && 
            topLeft->val == bottomRight->val) {
            return new Node(topLeft->val, true);
        }
        
        // 不能合并,创建内部节点
        return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
    }
};
class Solution:
    def intersect(self, quadTree1: 'Node', quadTree2: 'Node') -> 'Node':
        # 如果其中一个节点是叶子节点
        if quadTree1.isLeaf:
            # 如果quadTree1是1,则结果是1(1 OR anything = 1)
            return quadTree1 if quadTree1.val else quadTree2
        if quadTree2.isLeaf:
            # 如果quadTree2是1,则结果是1(anything OR 1 = 1)
            return quadTree2 if quadTree2.val else quadTree1
        
        # 两个都不是叶子节点,递归处理四个子节点
        topLeft = self.intersect(quadTree1.topLeft, quadTree2.topLeft)
        topRight = self.intersect(quadTree1.topRight, quadTree2.topRight)
        bottomLeft = self.intersect(quadTree1.bottomLeft, quadTree2.bottomLeft)
        bottomRight = self.intersect(quadTree1.bottomRight, quadTree2.bottomRight)
        
        # 检查是否可以合并为一个叶子节点
        if (topLeft.isLeaf and topRight.isLeaf and 
            bottomLeft.isLeaf and bottomRight.isLeaf and
            topLeft.val == topRight.val == bottomLeft.val == bottomRight.val):
            return Node(topLeft.val, True, None, None, None, None)
        
        # 不能合并,创建内部节点
        return Node(False, False, topLeft, topRight, bottomLeft, bottomRight)
public class Solution {
    public Node Intersect(Node quadTree1, Node quadTree2) {
        // 如果其中一个节点是叶子节点
        if (quadTree1.isLeaf) {
            // 如果quadTree1是1,则结果是1(1 OR anything = 1)
            return quadTree1.val ? quadTree1 : quadTree2;
        }
        if (quadTree2.isLeaf) {
            // 如果quadTree2是1,则结果是1(anything OR 1 = 1)
            return quadTree2.val ? quadTree2 : quadTree1;
        }
        
        // 两个都不是叶子节点,递归处理四个子节点
        Node topLeft = Intersect(quadTree1.topLeft, quadTree2.topLeft);
        Node topRight = Intersect(quadTree1.topRight, quadTree2.topRight);
        Node bottomLeft = Intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
        Node bottomRight = Intersect(quadTree1.bottomRight, quadTree2.bottomRight);
        
        // 检查是否可以合并为一个叶子节点
        if (topLeft.isLeaf && topRight.isLeaf && 
            bottomLeft.isLeaf && bottomRight.isLeaf &&
            topLeft.val == topRight.val && 
            topLeft.val == bottomLeft.val && 
            topLeft.val == bottomRight.val) {
            return new Node(topLeft.val, true, null, null, null, null);
        }
        
        // 不能合并,创建内部节点
        return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
    }
}
var intersect = function(quadTree1, quadTree2) {
    if (quadTree1.isLeaf) {
        if (quadTree1.val) {
            return quadTree1;
        } else {
            return quadTree2;
        }
    }
    
    if (quadTree2.isLeaf) {
        if (quadTree2.val) {
            return quadTree2;
        } else {
            return quadTree1;
        }
    }
    
    let topLeft = intersect(quadTree1.topLeft, quadTree2.topLeft);
    let topRight = intersect(quadTree1.topRight, quadTree2.topRight);
    let bottomLeft = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
    let bottomRight = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
    
    if (topLeft.isLeaf && topRight.isLeaf && bottomLeft.isLeaf && bottomRight.isLeaf &&
        topLeft.val === topRight.val && topLeft.val === bottomLeft.val && topLeft.val === bottomRight.val) {
        return new _Node(topLeft.val, true, null, null, null, null);
    }
    
    return new _Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n)n是四叉树中节点的总数,每个节点最多访问一次
空间复杂度O(h)h是四叉树的高度,递归调用栈的深度,最坏情况下为O(log n)