LeetCode 655. Print Binary Tree

image.png

问题描述

将一颗二叉树以 m*n 二维数组的形式打印出来,满足如下条件:

  1. 数组行数等于二叉树高度。
  2. 数组列数始终是奇数。
  3. 根节点的值(以字符串表示)在第一行的正中间。根节点所在的行和列将剩余空间分成左下和右下两部分。将左子树打印在左下部分,右子树打印在右下部分,并且两部分所占空间相同。如果一个子树为空,但是另一个子树非空,不需要打印空的子树,但是需要预留出跟非空子树相同的空间。如果两个子树都为空,则不需要预留空间。
  4. 没有用到的空间用 "" 表示。
  5. 子树的打印也遵循同样的规则。

栗 1:

输入:
    1
    /
   2
   
输出:

[["", "1", ""],
 ["2", "", ""]]
 

栗 2:

输入:
     1
    / \
   2   3
    \
     4

输出:

[["", "", "", "1", "", "", ""],
 ["", "2", "", "", "", "3", ""],
 ["", "", "4", "", "", "", ""]]

栗 3:

输入:
      1
     / \
    2   5
   / 
  3 
 / 
4 

输出:
[["",  "",  "", "",  "", "", "", "1", "",  "",  "",  "",  "", "", ""]
 ["",  "",  "", "2", "", "", "", "",  "",  "",  "",  "5", "", "", ""]
 ["",  "3", "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]
 ["4", "",  "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]]

注意:树的高度在 [1, 10] 之间。

想看英文原文的戳这里

解题思路

我的解法

将我的解法与答案区的解法相比,顿时觉得自己思路“清奇”,竟然能想出这种旁门左道的方式。

规则解析

题目的描述很长,规则也不太容易理解。在磕磕绊绊之下,通过试验和分析 testcase 的正确答案与自己答案的区别后,终于悟出了其所要表达的含义。

主要来说下第 3/5 点规则,这么一大串描述看着都头大。简化如下:

  • 根节点所在的列需要在数组的正中间。
  • 左右子树所占的空间相等。即使有一个子树为空,也需占据空间。
  • 每颗子树都要遵循相同的规则。也就是说,不仅仅针对于根节点,对于所有节点开始的子树,如出一辙。(这点很重要,不然栗子会看不懂)

最难理解的部分就是「左右子树所占的空间相等」。特别是当一个子树为空,另一个非空时。

等空间

由于左右子树空间相等,所以某棵子树所占的空间(也可理解为所占的列数),等于「其左右子树中较大的空间 * 2 + 1」+1 是指它本身所占一列。这点应该比较好理解。

举几个栗子。

栗 1:


image.png

很明显,以 1 为根节点的树,所占空间为 3,因为左右子树都只有 1 个节点。

栗 2:


image.png

1 为根节点的树,所占空间为 7。为什么是 7 呢?

这需要分别计算出以 32 开始的子树所占的空间,取其大者。

  • 3 开始的子树所占空间为 3。因为左子树 41 个空间,而左右子树需要有相同空间,因此总空间为 2*1+1=3
  • 2 开始的子树所占空间为 1

因此,1 所占的空间为 2*3+1=7

不清楚的可以看这张图,我将空间扩展的部分画了出来。

image.png

栗 3:
看个更复杂些的二叉树。

根节点 1 占据的空间是多少呢?你可以自己先想一下,答案是15

我们逐个节点进行分析:

  • 计算节点 1 的空间,需要计算出节点 32 的空间。
  • 节点 2 的空间,肉眼可见为 1
  • 节点 3 的空间,需要计算出 45 的空间。
  • 4 的空间为 1
  • 5 的空间,需要计算 6 的空间。
  • 6 的空间为 1
  • 再逐步往上退,5 的空间为 2*1+1=3
  • 3 的空间,取 4/5 中最大的再做运算,为 2*3+1=7
  • 1 的空间,取 2/3 中最大的再做运算,为 2*7+1=15

同样,下图是扩展后的空间。

image.png

从上述几个栗子中,我们可以总结出节点空间的计算方法。

// 父节点空间 = 左右子树空间最大值 * 2 + 1
f(node) = max(f(node.left), f(node.right)) * 2 + 1

思路

在了解等空间的概念后,下面来说说我自己的思路。

在二维矩阵中填入节点值,就得知道每个节点所在的行和列。行数很好求,因为在遍历过程中可知道当前层数,主要是列数的求法。

首先如果我们将整体的列数求出来,那么根节点的位置是知道的。更进一步,如果知道了子节点与父节点的相差列数,那么子节点的位置也可求出。所以我的主要思路就是利用子节点与父节点的相差列数来计算所有节点位置。

  • 对于每个节点,其所占的空间是可以求出来的。
  • 每个节点与其父节点的宽度距离,即相差的列数,也能求出。即其左右子树最大空间。
  • 每层节点与其父节点的距离都是相同的,取各个节点计算出来的最大值。
  • 最终算出根节点所占的总列数,则根节点的位置可以确定。
  • 再次从根节点遍历二叉树,由于每层节点距父节点的宽度已算出,则左右子节点所在的位置也可知。
    假设 distance 为下一层的距离宽度,col 为当前列。
    • 左节点所在列:col - distance - 1
    • 右节点所在列:col + distance + 1

由于代码有点长,就不贴出来了,感兴趣的同学可以点此查看

更优解法

翻了翻评论区的解法,找到另外一种新的思路。

由于是等空间,那么最终就是一个满二叉树。其实从上面的扩展空间的图也可以看出。

其实数组的列数就等于总节点数,因为每个节点都占一列。而满二叉树的总节点数为 2^h-1,所以列数也为 2^h-1

同时数组的行数,也就是树的高度,我们可以预先求出。在知道了数组的行数和列数之后,下面就好办了。

假设 l 为左边界列,r 为右边界列,那么父节点所在的列数为 m=(1+r)/2。对于左节点,其右边界为 m-1,边界范围为 [l, m-1];右节点的左边界为 m+1,边界范围为 [m+1, r],这样就可以逐个求出节点所在的位置。

具体实现可点此查看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345