Leetcode--Tree

94. Binary Tree Inorder Traversal

中序 inorder:左节点->根节点->右节点

前序 pre-order:根节点-左节点-右节点

后序 post-order: 左节点-右节点-根节点

注意:因为每次pop出来的是最后一个元素,所以push时应该按相反的顺序来push

inorder:

nodelist.append((node.right, False))

nodelist.append((node, True))

nodelist.append((node.left, False))

pre-order:

nodelist.append((node.right, False))

nodelist.append((node.left, False))

nodelist.append((node, True))

post-order:

nodelist.append((node, True))

nodelist.append((node.right, False))

nodelist.append((node.left, False))

96. Unique Binary Search Trees

给定一个值n,可以构建多少个存储1到n的BST? 这题用到了动态规划

Suppose you are given 1--n, and you want to generate all binary search trees. How do you do it? Suppose you put number i on the root, then simply 

1. Generate all BST on the left branch by running the same algorithm with 1--(i-1), 

2. Generate all BST on the right branch by running the same algorithm with (i+1)--n.

3. Take all combinations of left branch and right branch, and that's it for i on the root.

Then you let i go from 1 to n.

95. Unique Binary Search Trees II

这题跟96题类似,用的方法是divide and conquer

当n=0时,应该返回[]而不是[[]]

98. Validate Binary Search Tree

一个很重要的性质:二叉搜索树的中序遍历之后数值是有序的,所以先进行二叉树中序遍历,再检查遍历的结果是否有序。但需要注意的是,这道题要求左节点小于root,root又小于右节点,都不包含等于。所以最后的判断条件要用for循环来两个两个的进行比较。

99. (Hard) Recover Binary Search Tree 

这道题没有实现。

The first element is always larger than its next one while the second element is always smaller than its previous one.

思路来自于:https://discuss.leetcode.com/topic/3988/no-fancy-algorithm-just-simple-and-powerful-in-order-traversal/2

The space usage is O(tree height), which could be O(lgn) in the best case and O(n) for the worst.

**python最小整数:-sys.maxsize-1

100. Same Tree

有recursively和iteratively两种实现方法

101. Symmetric Tree

没有根的时候,要返回true

recursive方法: 需要注意的一点就是函数必须传进来root.left和root.right两个参数,不能只传一个,因为只传一个的时候,你只能比较root.left和root.right是否相等,这种情况只适用于第二层,再往下就不对了,比如第三层,1,2,2,1 才是对称的,需要比较root.left.left 和root.right.right, 以及root.left.right和root.right.left

iterative方法:append的时候需要注意顺序,因为pop是最后一个元素,所以append也要反着来:

p.append(p1.left)  p.append(p1.right)

q.append(q1.right)  q.append(q1.left)

102. Binary Tree Level Order Traversal

注意的点是:res.append([node.val for node in level])  这样就可以把每层的值放在同一个list里。

这道题的思路是,维护三个list,一个是最后结果res,一个是当前层level,一个是下一层next。当level存在时,每次循环把node.left,node.right存到下一层中,针对每个node都这样做。最后判断next是否为空,若不为空,就把它传给level。当当前层为叶子层时,下一层就为空

103. Binary Tree Zigzag Level Order Traversal

跟上一题不同的地方就是zigzag,可以用一个计数器,从1开始,当计数器对2取余为1时,便正向赋值,否则就反向赋值:res.append([node.val for node in level[::-1]])

循环最后应该讲计数器加1

104. Maximum Depth of Binary Tree

Iterative方法:和上几道题一样,也是BFS,用两个list, 一个存放当前层,一个存放下一层,如果下一层不为空,depth就加1. depth最开始从1开始,如果要从0开始,就在返回结果的时候加1.  

recursive方法:新建一个helper函数,传进去的参数有node, depth,这里的depth从0开始,不然就会出错。因为helper里当node存在事depth就会加1. 并且返回用node.left和node.right作为参数时的最大值。

return max(self.helper(node.left, depth), self.helper(node.right, depth))

当node不存在,就返回depth

105. Construct Binary Tree from Preorder and Inorder Traversal

Preorder的第一个元素是根preorder.pop(0),取得根的index之后:

root.left = self.buildTree(preorder, inorder[:index])

root.right = self.buildTree(preorder, inorder[index+1:])

注意这里是先赋值left,再赋值right,顺序反过来不对

判断条件只能是 if inorder:

106. Construct Binary Tree from Inorder and Postorder Traversal

Postorder里最后一个元素是根, postorder.pop()

root.right = self.buildTree(inorder[:index], postorder)

root.left = self.buildTree(inorder[index+1:], postorder)

这里是先赋值right,再赋值left,顺序不可以反过来

为什么呢?因为pop总是pop最右边的元素,在postorder中,[左,右,根],当根被pop出去之后,下一个被pop的就是右子树,所以要先对root.right进行操作

判断条件只能是 if inorder:

107. Binary Tree Level Order Traversal II (bottom-up

一个方法就是对原来的level traversal结果进行reverse

另一个方法就是使用nodelist(stack), 存放节点和深度,每次pop出一个元素,需要注意的是,当res的长度小于depth时,要在res中插入:res.insert(0, [])

向nodelist中添加元素需要注意顺序,如果先左后右,就要pop(0),如果先右后左,就直接pop()

level从1开始

108. Convert Sorted Array to Binary Search Tree

105和106的简化版,只给一个sorted array,因为BST的inorder遍历是有序数列,所以每个数列的nums[len(nums)/2]为根,再递归地调用原函数,得到left和right

110. Balanced Binary Tree

这道题用到了求深度的函数,对根的左右子树求深度,看他们的绝对值是否小于等于1,并且左右子树是否也是平衡树,根据平衡树的定义可以写出来return语句

`return abs(self.helper(root.left, 1) - self.helper(root.right, 1)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)`

111. Minimum Depth of Binary Tree

要注意的地方 1· 向helper中传参数的时候,root的depth应该是0,因为此时root已被证实存在,helper函数会将depth加1

2· helper函数里的判断条件,要比求最大深度时多一些。因为最小深度的定义是:从根节点到最近的叶子节点的最短距离 The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 所以判断条件里要有,if not node.left

if not node.right。 当左节点不存在,就用右节点做参数传递到helper中,同时depth加1,同样,右节点不存在时,用左节点做参数。这是因为,如果左节点不存在,而右节点存在,那说明左节点不是叶子节点,所以要继续右节点。当左右都存在时,就返回他们的MIN值

** 叶子节点的度为0!

112. Path Sum

Iterative: 又是树的路径问题,维护一个nodelist,每个元素是(node, node,val), 不断更新nodelist以及其中的node.val,最后看sum在不在res数组里。DFS

Recursive:  当没有根,返回F,当没有左右子树,根的值又等于sum,返回T。否则就讲root.val从sum中减去,成为新的sum,返回以左子树和新的sum为参数的递归  或者以右子树和新的sum做参数的递归。因为只要有一个为真,结果就为真,所以是or的关系

sum -= root.val

return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum)

113. Path Sum II

要求返回满足和相等的路径

iterative方法:依然是nodelist,只不过这次的nodelist里每个元素不再是两个参数,而是三个,一个是node, 一个是node.val, 一个是[node.val], 第二个用来叠加路径和,第三个用来存放路径。注意在更新nodelist时,第二个node.val可以直接叠加: value+node.left.val,第三个要在list的基础上叠加:path + [node.left.val],这样就相当于append了

recursive方法:这次的helper函数用到了四个参数,node, sum, path, res,当没有左右子树且node.val == sum(sum一直在减少)时,将node.val添加到path中,再将path添加到res中。

如果有左右子树,就递归调用helper函数,但是参数要进行更新

self.helper(node.left, sum - node.val, path + [node.val], res)

self.helper(node.right, sum - node.val, path + [node.val], res)

当node不存在时,直接返回

114. Flatten Binary Tree to Linked List

同样有递归和迭代两种方法,注意的是,在转换成linkedlist时,root前一定要有一个pre node来指向root。

Iterative: 依然维护一个nodelist,每次从nodeList中pop出来一个元素,将pre.right指向这个元素,pre.left = None,pre初始化为任意一个treenode(pre = TreeNode(-1)). 然后如果node.left存在,将其append进nodelist, node.right也同样。最后将pre = node, 即当前的node变为新的pre. 因为Pop是取出最后一个元素,所以要先append node.right, 再append node.left

Recursive: 将pre的初始化写在__init__函数里,self.pre = None, 递归调用函数本身,先以root.right为参数,再以root.left为参数。然后将

root.right = self.pre,  root.left = None,    self.pre = root.   

感觉这是dfs, 先进入到最后一层,再一层一层向上操作。所以要将root.right指向self.pre,self.pre的初始值为空

116. Populating Next Right Pointers in Each Node

理解题意时有很重要的一点就是,因为已经初始化了所有的node的next指针为null,所以每一行最后边那个node是不用管的,它的next已经指向了null。

使用一个pre指针,让它总是指向root

while循环的判断条件为while root.left,因为我们在当前行就可以执行完下一行的任务,所以无需将root循环到最后一行。

if 循环的判断语句为if root.next,意思是检查当前root的next是指向空,还是已经指向了某个node,如果它不指向空,我们就root.right.next = root.next.left, 并把root.next作为新的root

如果它指向空,root = pre.left ;  pre = root;  我们就把pre.left作为新的root, 即向右移动了一个node。

** 改变root的值时,一定是要root = pre.left, 不能是root = root.left

**当root.next存在时,证明root.next已经指向了某一个元素,现在就应该将root.right.next指向root.next.left, 即将两个子树之间产生联系

117. Populating Next Right Pointers in Each Node II

这题是上一题的follow up,上一题假设了是完美二叉树,all leaves are at the same level, and every parent has two children,这一题说的是可能是任何二叉树。

先初始化两个TreeLinkNode, tail 和 dummy,root 代表当前层的节点,tail代表下一层的节点。while root:让tail.next指向root.left,然后判断tail.next是否存在,若存在,就将tail向后移,tail = tail.next, 然后将tail.next指向root.right,再次判断tail.next是否存在,若存在就向后移,然后让root = root.next,判断root是否还存在,若为空了,则将dummy赋值给tail, 将dummy.next指向root

129. Sum Root to Leaf Numbers

将path转换为数字,然后求所有path转换之后的总和。求path的过程和之前的题目一样,但是path不是存成数组的形式,而是以字符的形式存放,每次更新时:

path + str(node.left.val)  注意:1,要用加号 2,要转换为str形式

最后再将每一个path转换为int形式再全部相加就可以了


124. Binary Tree Maximum Path Sum

http://www.jianshu.com/p/c3e81355831d

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

推荐阅读更多精彩内容