代码随想录算法训练营第十八天|513. 找树左下角的值,路径总和,从中序与后序遍历序列构造二叉树
513. 找树左下角的值
题目链接:找树左下角的值
看了一眼提示迭代简单,递归有难度,果然递归写了一个小时发现提看错了,不是最底层的左叶子,右叶子也可以的!!!只要是最后一层最左边的就行,写完了发现右叶子也行。
迭代
class Solution(object):
def findBottomLeftValue(self, root):
"""
:type root: TreeNode
:rtype: int
"""
queue = collections.deque()
res = []
queue.append(root)
size = 1
while queue:
l = []
for _ in range(size):
cur = queue.popleft()
l.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
res.append(l)
size = len(queue)
return res[-1][0]
这个题迭代确实很容易,就是层序遍历最后一层的第一个元素就行。
顺便这里提醒一下自己,在append进l的时候,最好在popleft的时候append,别在append进queue的时候append,不然会多一个空list的。
递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
max_depth = -inf
max_node = root.val
def traversal(root,depth):
nonlocal max_depth, max_node
if (not root.left) and (not root.right):
if max_depth < depth:
max_depth=depth
max_node = root.val
if root.left:
traversal(root.left,depth+1)
if root.right:
traversal(root.right,depth+1)
traversal(root,0)
return max_node
还是回溯,为什么不用
depth+=1
traversal(root.left,depth+1)
depth-=1
113里会写
nonlocal和global
- global是全局变量,变量定义在函数外部的时候,如果函数里面想改变这个全局变量的值,需要在当前的引用函数里面重新定义一个变量 并用关键字global修饰。
a=1
def b():
global a
a+=1
print(a)
b()
- nonlocal非全局变量,在函数的函数里面使用函数的变量。
def b():
num2=1
def c():
nonlocal num2#为了修改非全局变量
num2+=2
print(num2)
return c
b()
这道题是def套def用unlocal。
路径总和
112. 路径总和
题目链接:路径总和
这题什么都不写的时候自动输出False,PathSum最后的return False
不写也没事。
在哪里要return上搞了很久
错误return
查了半天,sum都算出来了,就是不出True,最后理了一遍,问题应该在return上,在if root.left:
和root.right:
这里,就算PathSum(root.left,sum+root.left.val,targetSum)
得到了True,没有return就等于啥也没有。
但是直接return PathSum(root.left,sum+root.left.val,targetSum)
也是错的,因为这样整个function就直接断掉了。
class Solution(object):
def hasPathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: bool
"""
def PathSum(root,sum,targetSum):
if (not root.left) and (not root.right):
if sum == targetSum:
return True
if root.left:
PathSum(root.left,sum+root.left.val,targetSum)
if root.right:
PathSum(root.right,sum+root.right.val,targetSum)
return False
if not root:
if targetSum != 0:
return False
else:
return PathSum(root,root.val,targetSum)
递归
正确的办法是得到True了,return一下。
class Solution(object):
def hasPathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: bool
"""
def PathSum(root,sum,targetSum):
if (not root.left) and (not root.right):
#t(sum)
if sum == targetSum:
#print(1)
return True
if root.left:
if PathSum(root.left,sum+root.left.val,targetSum):
return True
if root.right:
if PathSum(root.right,sum+root.right.val,targetSum):
return True
return False
if not root:
if targetSum != 0:
return False
else:
return PathSum(root,root.val,targetSum)
简洁版递归
因为不知道要怎么统计sum所以多写了一个函数,可以直接在targetSum上动。
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
if not root.left and not root.right:
if targetSum==root.val:
return True
else:
return False
else:
return self.hasPathSum(root.left,targetSum-root.val) or self.hasPathSum(root.right,targetSum-root.val)
迭代
很久以前自己写的迭代,有空再写一次吧。
class Solution(object):
def hasPathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: bool
"""
from collections import deque
if not root:
return False
que_root=deque([root])
que_sum=deque([root.val])
while que_root:
node=que_root.popleft()
s=que_sum.popleft()
if not node.left and not node.right:
if targetSum==s:
return True
if node.left:
que_root.append(node.left)
que_sum.append(s+node.left.val)
if node.right:
que_root.append(node.right)
que_sum.append(s+node.right.val)
return False
113. 路径总和ii
题目链接:路径总和ii
递归
class Solution(object):
def pathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: List[List[int]]
"""
def whichpath(root,path,targetSum,res):
if (not root.left) and (not root.right):
if sum(path) == targetSum:
res.append(path[:])#这里一定要加:
else:
if root.left:
path.append(root.left.val)
whichpath(root.left,path,targetSum,res)
path.pop()
if root.right:
path.append(root.right.val)
whichpath(root.right,path,targetSum,res)
path.pop()
res = []
path = []
if not root:
return res
path.append(root.val)
whichpath(root,path,targetSum,res)
return res
关于path[:]:中间不可以写path,因为path是引用,而path[:]是拷贝数据进去,引用的话,这么递归下去,path自己发生了改变,会影响到res里已经append进去的path,所以最后的得到的答案都是只有[root.val](递归到最后得到的);如果是path[:]就是复制切片,所以后面的递归里path发生了改变也不会影响到复制体。
path是list所以一定要pop,上一题,sum是个值,包括昨天的回溯,path也是个值,在进入递归之后会产生新的值,所以没有关系,但这里是list,每次都是append进去,并不会有一个新的list出现,所以每次都要pop。
从中序与后序遍历序列构造二叉树
106.从中序与后序遍历序列构造二叉树
题目链接:从中序与后序遍历序列构造二叉树
这个题最重要的是所有元素不重复,所以后序的最后一个元素是root,在中序找到这个元素就可以找到左右孩子的长度而不用担心会不会重复。
中序:左中右
后序:左右中
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if len(inorder) == 0:
return None
tree = TreeNode(val=postorder[-1])
r = inorder.index(postorder[-1])
if len(inorder) == 1:
return tree
tree.left = self.buildTree(inorder[:r], postorder[:r])
tree.right = self.buildTree(inorder[(r+1):], postorder[r:(len(postorder)-1)])
return tree
105.从前序与中序遍历序列构造二叉树
题目链接:从前序与中序遍历序列构造二叉树
这个也差不多。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if len(inorder) == 0:
return None
tree = TreeNode(val=preorder[0])
r = inorder.index(preorder[0])
if len(inorder) == 1:
return tree
tree.left = self.buildTree(preorder[1:(1+r)],inorder[:r])
tree.right = self.buildTree(preorder[(1+r):],inorder[(r+1):])
return tree