236 二叉树的最近公共祖先
不会做,看了视频讲解思路后自己写出来了
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root: return None
if root.val == p.val: return p
if root.val == q.val: return q
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
if left != None and right == None:
return left
if left == None and right != None:
return right
if left != None and right != None:
return root
if left == None and right == None:
return None
非常巧妙地包含了pq分布在不同子树和相同子树上的两种情况,使用后续遍历,回溯记录是否访问到了p和q,当某节点回溯同时遇到pq时则说明其是最近公共祖先
235 二叉搜索树的最近公共祖先
使用上一题的思路,添加了根据root的val判断左右子树,结果无法通过了,为什么?
这思路有问题,不能根据root的val判断左右子树,这样会在找pq时遍历两遍树,看解答发现压根不需要判断,直接从上往下找第一个值在pq中间的即可
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root == None or root == p or root == q: return root
if (root.val < p.val and root.val > q.val) or (root.val > p.val and root.val < q.val):
return root
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
return left or right
不过实际写出来的思路还跟解答的实现思路不太一样,解答是我一开始想到的思路的正确版本,要判断root同时大于pq或同时小于pq的情况,而不是分别比p和比q
不过解答的迭代法挺简洁的,值得学习
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
while root:
if root.val < p.val and root.val < q.val:
root = root.right
elif root.val > p.val and root.val > q.val:
root = root.left
else:
return root
return None
701 二叉搜索树中的插入操作
使用迭代和二叉搜索树的性质寻找插入位置,然后插入
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
temp = root
node = TreeNode()
node.val = val
if root == None:
return node
while temp:
if temp.val > val:
if temp.left != None:
temp = temp.left
else:
temp.left = node
break
elif temp.val < val:
if temp.right != None:
temp = temp.right
else:
temp.right = node
break
return root
以后一定得注意检查输入节点为空的情况!
再用递归写一下试试
没成功,有个算例莫名其妙无法通过,看了下解答思路比我清晰许多
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root:
node = TreeNode(val)
return node
if root.val < val:
root.right = self.insertIntoBST(root.right,val)
if root.val > val:
root.left = self.insertIntoBST(root.left,val)
return root
450 删除二叉搜索树中的节点
分析得知更新二叉搜索树应当是右边节点提上来,左边节点加到右子树的最左边
但要分几种情况讨论,若删除节点为叶子节点,则无需更新
若删除节点只有左子树或右子树,则直接提上来
若删除节点同时有左右子树,则需要更新
先用迭代写,逻辑太绕了,写得十分丑陋,简直是做得最丑陋的答案之一
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
## 首先找到删除节点
if not root: return root
temp = root
pre = None
while temp.val != key:
if temp.val < key:
pre = temp
temp = temp.right
elif temp.val > key:
pre = temp
temp = temp.left
if temp == None:
return root
if not temp.left and not temp.right:
if pre == None:
return None
if pre.left != None:
if pre.left.val == key:
print(1)
pre.left = None
if pre.right != None:
if pre.right.val == key:
pre.right = None
elif temp.left and temp.right:
if pre == None:
temp = temp.right
while temp.left:
temp = temp.left
temp.left = root.left
return root.right
if pre.left != None:
if pre.left.val == key:
pre.left = temp.right
left = temp.left
temp = temp.right
while temp.left:
temp = temp.left
temp.left = left
if pre.right != None:
if pre.right.val == key:
pre.right = temp.right
left = temp.left
temp = temp.right
while temp.left:
temp = temp.left
temp.left = left
elif temp.left == None and temp.right != None:
if pre == None:
return root.right
if pre.left != None:
if pre.left.val == key:
pre.left = temp.right
if pre.right != None:
if pre.right.val == key:
pre.right = temp.right
else:
if pre == None:
return root.left
if pre.left != None:
if pre.left.val == key:
pre.left = temp.left
if pre.right != None:
if pre.right.val == key:
pre.right = temp.left
return root
看一下解答,递归还算简洁,迭代法也比较繁琐
我对情况的分析是没错的,但是key所在节点在前一个节点的左边还是右边,以及key出现在根节点的情况写得太麻烦了
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if root is None:
return root
if root.val == key:
if root.left is None and root.right is None:
return None
elif root.left is None:
return root.right
elif root.right is None:
return root.left
else:
cur = root.right
while cur.left is not None:
cur = cur.left
cur.left = root.left
return root.right
if root.val > key:
root.left = self.deleteNode(root.left,key)
if root.val < key:
root.right = self.deleteNode(root.right,key)
return root
实际上只是通过递归找到key所在节点,然后进行操作的。解答中另一种递归思路是找到后把key与右子树最左边节点交换,然后递归操作的
if pre.left and pre.left.val == key:
pre.left = self.deleteOneNode(cur)
if pre.right and pre.right.val == key:
pre.right = self.deleteOneNode(cur)
``
在递归中可以这样写来避免pre.left或pre.right报错,因为python会先判断第一个条件,如果为False就不再看第二个条件了(and情况下)
此外,python中is有时候很好用,它和==的区别在于,==判断两者内容是否相同,is则判断两者是不是同一个东西,如果内容相同但不是一个东西则is会返回False`