建立四叉树[中等]

2024-01-11 06:44
文章标签 中等 建立 四叉树

本文主要是介绍建立四叉树[中等],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、题目

给你一个n * n矩阵grid,矩阵由若干01组成。请你用四叉树表示该矩阵grid。你需要返回能表示矩阵grid四叉树的根结点。四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性:
【1】val:储存叶子结点所代表的区域的值。1对应True0对应False。注意,当isLeafFalse时,你可以把True或者False赋值给节点,两种值都会被判题机制接受。
【2】isLeaf: 当这个节点是一个叶子结点时为True,如果它有4个子节点则为False

class Node {public boolean val;public boolean isLeaf;public Node topLeft;public Node topRight;public Node bottomLeft;public Node bottomRight;
}

我们可以按以下步骤为二维区域构建四叉树:
【1】如果当前网格的值相同(即,全为0或者全为1),将isLeaf设为True,将val设为网格相应的值,并将四个子节点都设为Null然后停止。
【2】如果当前网格的值不同,将isLeaf设为False,将val设为任意值,然后如下图所示,将当前网格划分为四个子网格。
【3】使用适当的子网格递归每个子节点。

四叉树格式: 你不需要阅读本节来解决这个问题。只有当你想了解输出格式时才会这样做。输出为使用层序遍历后四叉树的序列化形式,其中null表示路径终止符,其下面不存在节点。它与二叉树的序列化非常相似。唯一的区别是节点以列表形式表示[isLeaf, val]。如果isLeaf或者val的值为True,则表示它在列表[isLeaf, val]中的值为1;如果isLeaf或者val的值为False,则表示值为0

示例 1:

输入:grid = [[0,1],[1,0]]
输出:[[0,1],[1,0],[1,1],[1,1],[1,0]]
解释:此示例的解释如下:请注意,在下面四叉树的图示中,0表示false1表示True

示例 2:

输入:grid = [[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0]]
输出:[[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
解释:网格中的所有值都不相同。我们将网格划分为四个子网格。topLeftbottomLeftbottomRight均具有相同的值。topRight具有不同的值,因此我们将其再分为4个子网格,这样每个子网格都具有相同的值。解释如下图所示:

n == grid.length == grid[i].length
n == 2x其中0 <= x <= 6

二、代码

【1】递归: 我们可以使用递归的方法构建出四叉树。具体地,我们用递归函数dfs(r0,c0,r1,c1)处理给定的矩阵gridr0行开始到r1−1行,从c0c1−1列的部分。我们首先判定这一部分是否均为01,如果是,那么这一部分对应的是一个叶节点,我们构造出对应的叶节点并结束递归;如果不是,那么这一部分对应的是一个非叶节点,我们需要将其分成四个部分:行的分界线为(r0+r1)/2​​,列的分界线为(c0+c1)/2​​,根据这两条分界线递归地调用dfs函数得到四个部分对应的树,再将它们对应地挂在非叶节点的四个子节点上。

class Solution {public Node construct(int[][] grid) {return dfs(grid, 0, 0, grid.length, grid.length);}public Node dfs(int[][] grid, int r0, int c0, int r1, int c1) {boolean same = true;for (int i = r0; i < r1; ++i) {for (int j = c0; j < c1; ++j) {if (grid[i][j] != grid[r0][c0]) {same = false;break;}}if (!same) {break;}}if (same) {return new Node(grid[r0][c0] == 1, true);}Node ret = new Node(true,false,dfs(grid, r0, c0, (r0 + r1) / 2, (c0 + c1) / 2),dfs(grid, r0, (c0 + c1) / 2, (r0 + r1) / 2, c1),dfs(grid, (r0 + r1) / 2, c0, r1, (c0 + c1) / 2),dfs(grid, (r0 + r1) / 2, (c0 + c1) / 2, r1, c1));return ret;}
}

时间复杂度: O(n^2log⁡n)。这里给出一个较为宽松的时间复杂度上界。记T(n)为边长为n的数组需要的时间复杂度,那么「判定这一部分是否均为01」需要的时间为O(n^2),在这之后会递归调用4规模为n/2的子问题,那么有:T(n)=4T(n/2)+O(n^2)以及:T(1)=O(1)根据主定理,可以得到T(n)=O(n^2log⁡n)。但如果判定需要的时间达到了渐近紧界Θ(n^2),那么说明这一部分包含的元素大部分都是相同的,也就是说,有很大概率在深入递归时遇到元素完全相同的一部分,从而提前结束递归。因此O(n^2log⁡n)的时间复杂度是很宽松的,实际运行过程中可以跑出与方法二O(n^2)时间复杂度代码相似的速度。
空间复杂度: O(log⁡n),即为递归需要使用的栈空间。

【2】递归 + 二维前缀和优化: 我们可以对方法一中暴力判定某一部分是否均为01的代码进行优化。具体地,当某一部分均为0时,它的和为0;某一部分均为1时,它的和为这一部分的面积大小。我们可以与处理出数组grid的二维前缀和,这样一来,当我们需要判定某一部分是否均为01时,可以在O(1)的时间内得到这一部分的和,从而快速地进行判断。

class Solution {public Node construct(int[][] grid) {int n = grid.length;int[][] pre = new int[n + 1][n + 1];for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) {pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + grid[i - 1][j - 1];}}return dfs(grid, pre, 0, 0, n, n);}public Node dfs(int[][] grid, int[][] pre, int r0, int c0, int r1, int c1) {int total = getSum(pre, r0, c0, r1, c1);if (total == 0) {return new Node(false, true);} else if (total == (r1 - r0) * (c1 - c0)) {return new Node(true, true);}Node ret = new Node(true,false,dfs(grid, pre, r0, c0, (r0 + r1) / 2, (c0 + c1) / 2),dfs(grid, pre, r0, (c0 + c1) / 2, (r0 + r1) / 2, c1),dfs(grid, pre, (r0 + r1) / 2, c0, r1, (c0 + c1) / 2),dfs(grid, pre, (r0 + r1) / 2, (c0 + c1) / 2, r1, c1));return ret;}public int getSum(int[][] pre, int r0, int c0, int r1, int c1) {return pre[r1][c1] - pre[r1][c0] - pre[r0][c1] + pre[r0][c0];}
}

时间复杂度: O(n^2)。在最坏情况下,数组grid中交替出现01,此时每一个叶节点对应着1×1的区域。记T(n)为边长为n的数组需要的时间复杂度,那么有:T(n)=4T(n/2)+O(1)以及:T(1)=O(1)根据主定理,可以得到T(n)=O(n^2)。预处理二维前缀和需要的时间也为O(n^2),因此总时间复杂度为O(n^2)
空间复杂度: O(n^2),即为二维前缀和需要使用的空间。

这篇关于建立四叉树[中等]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/593494

相关文章

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输

【中等】保研/考研408机试-二分查找(模板题)

二分查找就是在一个有序数组中查找某个值,以首端尾端的中点mid查找对比,mid与要查找的数进行对比,看落在哪个区间,在那个区间重新得到首端和尾端,进而得到新的mid值。 一、模板题 二分查找-I_牛客题霸_牛客网 class Solution {public:int search(vector<int>& nums, int target) {int left=0,right=nums.s

【内网】ICMP出网ew+pingtunnel组合建立socks5隧道

❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 通过环境搭建,满足以下条件: 攻击机模拟公网vps地址,WEB边界服务器(Windows Server 2008)模拟公司对外提供Web服务的机器,该机器可以通内网,同时向公网提供服务。内网同网段存在一台Windows内网服务

【IDEA】建立多个子模块依赖于一个父模块(maven)

第一步,建立父模块(在IDEA中就是工程) 第二步,选中父模块(也就是工程)右键New Module建立子模块 勾选创建模板原型并一般选择 maven-archetype-quickstart,当创建web模块时选择 maven-archetype-webapp 其他子模块都是类似这样创建~ packaging打包类型有: jar,默认类型warejbea

Java中等题-整数替换(力扣)

给定一个正整数 n ,你可以做如下操作: 如果 n 是偶数,则用 n / 2替换 n 。如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。 返回 n 变为 1 所需的 最小替换次数 。 示例 1: 输入:n = 8输出:3解释:8 -> 4 -> 2 -> 1 示例 2: 输入:n = 7输出:4解释:7 -> 8 -> 4 -> 2 -> 1或 7 ->

【2024全国大学生数学建模竞赛】B题 模型建立与求解(含代码与论文)

目录 1问题重述1.1问题背景1.2研究意义1.3具体问题 2总体分析3模型假设4符号说明(等四问全部更新完再写)5模型的建立与求解5.1问题一模型的建立与求解5.1.1问题的具体分析5.1.2模型的准备 目前B题第一问的详细求解过程以及对应论文部分已经完成! - 晚上7-8点之前第二问完成 - 明天中文之前全部写完 按照提交论文的格式进行撰写!完整版请看文章最后!

【UE4源代码观察】手动建立一个使用UBT进行编译的空白工程

我想观察UE4是怎么编译的,于是查阅官方文档,了解到UE4有一套自己的编译工具:UnrealBuildTool,简称UBT。关于UBT的官方文档参阅:虚幻编译工具。我想尝试自己手动建立一个使用UBT进行编译的空白工程。不过首先,先了解下UBT的编译流程中一些文件所扮演的角色 UBT的编译流程中一些文件所扮演的角色 模块 每个模块都由一个 .build.cs 文件声明,它存储在 Source

Java中等题-摆动序列(力扣)

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一

Linux - Tcp连接建立和释放的三次握手四次挥手

一、TCP报文段首部格式         源端口/目的端口:各占2个字节,分别写入源端口和目的端口,端口是传输层与应用层的服务接口    序号:占4个字节,TCP连接中传送的数据流中每一个字节都有一个序号,序号字段指本报文段所发送的数据的第一个字节的序号    确认号:占4个字节,是期望收到对方下一个报文的第一个数据字节的序号    数据偏移:占4个字节,它指出TCP报文的数据距离TCP

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码 1 比赛时间 北京时间:2024年9月5日 18:00-2024年9月8日20:00 2 思路内容 2.1 往届比赛资料 【2022高教社杯数学建模】C题:古代玻璃制品的成分分析与鉴别方案及代码实现(已经更新完毕) 【2022高教社杯数学建模】C题:古代玻璃制品的成分分析与鉴别 赛后总