二叉树篇
404. 左叶子之和
- 思路1:先找到二叉树中的叶子节点,然后对叶子节点的 左叶子求和。左叶子可以通过,该叶子节点是其父亲节点的左孩子确定。如果二叉树只有根节点这种特殊情况,左叶子和为0
class Solution(object):
def __init__(self):
self.sum = 0
def sumOfLeftLeaves(self, root):
if not root.left and not root.right: return 0
self.dfs(root,None)
return self.sum
def dfs(self,root,father):
if not root: return # 终止条件
if not root.left and not root.right: # 叶子节点
if father.left == root: # 左叶子
self.sum += root.val
self.dfs(root.left,root)
self.dfs(root.right,root)
总结:递归写法 1)先写终止条件 2)思考函数处理逻辑 3)递归调用函数自身
257. 二叉树的所有路径
- 思路1:前序遍历二叉树的节点,记录路径字符串 当访问到叶子节点,将其添加到结果数组
class Solution(object):
def __init__(self):
self.ret = []
def binaryTreePaths(self, root):
self.dfs(root,'')
return self.ret
def dfs(self,root,path):
if not root: return # 终止条件
if not root.left and not root.right:
self.ret.append(path+str(root.val))
self.dfs(root.left,path+str(root.val)+'->')
self.dfs(root.right,path+str(root.val)+'->')
112. 路径总和
- 思路1:前序遍历二叉树的节点,记录路径当前和,访问到叶子节点,路径当前和如果等于target,则存在题目要求路径,返回True;否则返回Fasle。只要存在一个这样的路径即可,因此用 或运算(or)
class Solution(object):
def hasPathSum(self, root, targetSum):
return self.dfs(root,targetSum,0)
def dfs(self,root,targetSum,curSum):
if not root: return False # 终止条件
if not root.left and not root.right:
curSum += root.val # 加上叶节点val
if curSum == targetSum:
return True
else:
return False
a = self.dfs(root.left,targetSum,curSum+root.val)
b = self.dfs(root.right,targetSum,curSum+root.val)
return a or b
113. 路径总和II
- 思路1:前序遍历二叉树的节点,记录路径当前和 以及路径节点,访问到叶子节点,路径当前和如果等于target,则添加路径。在记录路径过程中,采取回溯的思想
class Solution(object):
def __init__(self):
self.ret = []
self.nums = []
def pathSum(self, root, targetSum):
self.dfs(root,targetSum,0) # 最开始curSum初始为0
return self.ret
def dfs(self,root,targetSum,curSum):
if not root: return # 终止条件
self.nums.append(root.val)
if not root.left and not root.right:
curSum += root.val # 加上叶节点val
if curSum == targetSum:
self.ret.append(self.nums[:])
self.nums.pop(-1)
return
self.dfs(root.left,targetSum,curSum+root.val)
self.dfs(root.right,targetSum,curSum+root.val)
self.nums.pop(-1) # 回溯的思想
437. 路径总和III
- 思路1:采取两层深度优先遍历,第一层遍历二叉树的每个节点,第二层以每个节点为 根节点,进行路径和求和操作,采取回溯的思想统计满足题意的路径计数
- 思路2:我们利用先序遍历二叉树,记录下根节点 root 到当前节点cur路径上 除当前节点以外所有节点的前缀和,在已保存的路径前缀和中查找是否存在前缀和刚好等于当前节点到根节点的前缀和 cur 减去targetSum。
# 思路1
class Solution(object):
def __init__(self):
self.cnt = 0
self.curSum = 0
def pathSum(self, root, targetSum):
self.preOrder(root,targetSum)
return self.cnt
def preOrder(self,root,targetSum):
if not root: return
self.dfs(root,targetSum)
self.preOrder(root.left,targetSum)
self.preOrder(root.right,targetSum)
def dfs(self,root,targetSum):
if not root: return # 终止条件
self.curSum += root.val
if self.curSum == targetSum: # 计数加1
self.cnt += 1
self.dfs(root.left,targetSum)
self.dfs(root.right,targetSum)
self.curSum -= root.val # 回溯
# 思路2
class Solution:
def __init__(self):
self.prefix = collections.defaultdict(int)
def pathSum(self, root, targetSum):
self.prefix[0] = 1
return self.dfs(root, 0,targetSum)
def dfs(self,root, cur,targetSum):
if not root:
return 0
cur += root.val
ret = 0
ret += self.prefix[cur - targetSum]
self.prefix[cur] += 1
ret += self.dfs(root.left, cur,targetSum)
ret += self.dfs(root.right, cur,targetSum)
self.prefix[cur] -= 1 # 回溯
return ret
129. 求根节点到叶节点数字之和
- 思路1:前序遍历二叉树的节点,记录路径字符串 当访问到叶子节点,将路径字符串转成int数字,并累加起来即可
class Solution(object):
def __init__(self):
self.ret = 0
def sumNumbers(self, root):
self.dfs(root,'')
return self.ret
def dfs(self,root,path):
if not root: return # 终止条件
if not root.left and not root.right:
self.ret += int(path+str(root.val))
self.dfs(root.left,path+str(root.val))
self.dfs(root.right,path+str(root.val))
54. 二叉搜索树的第k大节点
- 思路1:采取中序遍历的,但是采取降序的方式 即先访问右孩子,再访问中间节点,再访问左孩子当访问到第k个节点 结束dfs,并返回该节点
class Solution(object):
def __init__(self):
self.cnt = 0
self.ret = 0
def kthLargest(self, root, k):
self.dfs(root,k)
return self.ret
def dfs(self,root,k):
if not root: return
self.dfs(root.right,k)
self.cnt += 1
if self.cnt == k:
self.ret = root.val
return
self.dfs(root.left,k)
230. 二叉搜索树中第K小的元素
- 思路1:采取中序遍历的,但是采取升序的方式 即先访问左孩子,再访问中间节点,再访问右孩子当访问到第k个节点 结束dfs,并返回该节点
class Solution(object):
def __init__(self):
self.cnt = 0
self.ret = 0
def kthSmallest(self, root, k):
self.dfs(root,k)
return self.ret
def dfs(self,root,k):
if not root: return
self.dfs(root.left,k)
self.cnt += 1
if self.cnt == k:
self.ret = root.val
return
self.dfs(root.right,k)
108. 将有序数组转换为二叉搜索树
- 思路1:采取递归+双指针做法,递归过程中采取二分的思想 根据有序数组重构二叉树即可
class Solution(object):
def sortedArrayToBST(self, nums):
i,j = 0,len(nums)-1
return self.dfs(nums,i,j)
def dfs(self,nums,i,j):
if i>j: return None
mid = (i+j) // 2
tmp = TreeNode(nums[mid])
tmp.left = self.dfs(nums,i,mid-1)
tmp.right = self.dfs(nums,mid+1,j)
return tmp
总结:一般涉及到数组和二叉树的题目,都会采取dfs的做法 。而且一般是 递归+双指针
1038. 把二叉搜索树转换为累加树
思路1:先先序遍历 记录整棵树的累计和sum 再根据中序遍历记录访问到目前为止节点的累计和curSum,然后将当前节点值赋值成sum-curSum
class Solution(object):
def __init__(self):
self.curSum = 0
self.sum = 0
def bstToGst(self, root):
self.preOrder(root)
self.inOrder(root)
return root
def preOrder(self,root):
if not root: return
self.sum += root.val
self.preOrder(root.left)
self.preOrder(root.right)
def inOrder(self,root):
if not root: return None
self.inOrder(root.left)
tmp = root.val
root.val = self.sum - self.curSum
self.curSum += tmp
self.inOrder(root.right)