前序遍历的顺序是:中左右。
中序遍历是:左中右。
后序遍历是:左右中。
其实表示的就是中在其中所处的位置。

- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def inorderTraversal(self, root):
- """
- :type root: TreeNode
- :rtype: List[int]
- """
- # 中序遍历是左中右
- # 这是深度优先搜索dfs
- # 一般是递归法和迭代法
- def dfs(cur, value):
- if cur == None:
- return
-
- dfs(cur.left, value)
- value.append(cur.val)
- dfs(cur.right, value)
-
- value = []
- dfs(root, value)
- return value

递归比较简单,主要还是要掌握迭代的做法。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def inorderTraversal(self, root):
- """
- :type root: TreeNode
- :rtype: List[int]
- """
- # 中序遍历是左中右
- # 这是深度优先搜索dfs
- # 一般是递归法和迭代法
- # 用迭代法
- # 栈,用来储存节点地址
- stack = []
- # 用来储存结果
- res = []
- while root or stack:
- # 先把左节点一直走到底
- if root:
- stack.append(root)
- root = root.left
- # 如果左节点都放入栈中了
- else:
- # 弹出栈中最上面的节点
- temp = stack.pop()
- # 储存该节点的值
- res.append(temp.val)
- # 将该节点的右子节点作为根节点遍历,如果没有右节点这个就是左,再次弹出最上面的节点,储存值,这个值是中,再以该节点的右子节点作为根节点,这个值是右。
- root = temp.right
-
- return res

心得:不知道为什么使max_deepth为数值的时候,输出的总是初始值,明明在函数里变化了的。最后只好改成了数组,输出数组最后的值。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def maxDepth(self, root):
- """
- :type root: TreeNode
- :rtype: int
- """
- # 遍历二叉树,用深度优先搜索的方式
- # 就用前序遍历吧,顺序是中左右
- # 先用递归法,后用迭代法
-
- def dfs(root, deepth, max_deepth):
- if not root:
- return
- deepth += 1
- if max_deepth[-1] < deepth:
- max_deepth.append(deepth)
- dfs(root.left, deepth, max_deepth)
- dfs(root.right, deepth, max_deepth)
- deepth -= 1
-
- deepth = 0
- max_deepth = [0]
- dfs(root, deepth, max_deepth)
-
- return max_deepth[-1]

心得:二叉树是一个天然的递归,算最大深度只需要算每个小树的深度,也就是左树深度+右树深度+1,不断递归得到。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def maxDepth(self, root):
- """
- :type root: TreeNode
- :rtype: int
- """
- # 遍历二叉树,用深度优先搜索的方式
- # 就用前序遍历吧,顺序是中左右
- # 先用递归法,后用迭代法
- # 用栈
- if root == None:
- return 0
- left = self.maxDepth(root.left)
- right = self.maxDepth(root.right)
- deepth = max(left,right)
-
- return deepth+1

- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def invertTree(self, root):
- """
- :type root: TreeNode
- :rtype: TreeNode
- """
- steam = root
- def invert(root):
- if root == None:
- return
- # 翻转大树,小树也要翻转,一眼递归
- temp = root.left
- root.left = root.right
- root.right = temp
- invert(root.left)
- invert(root.right)
-
- invert(root)
-
- return steam

给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:

心得:自己能想到怎么做,但是代码不知道怎么写,解析是定义了一个新函数来判断。应该思考到如果轴对称需要满足几个条件,两个指针分别指向左右子树,两个指针的val值相等,并且左指针的左子树等于右指针的右子树。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def isSymmetric(self, root):
- """
- :type root: TreeNode
- :rtype: bool
- """
- # 递归,左右同时开始,结构一样就继续往下,不一样就返回false
- # 层遍历
- # 或者分成左右两个树,每一步都同时往下深度优先搜索
- return self.check(root, root)
-
- def check(self, p, q):
- if p==None and q==None:
- return True
- if p==None or q==None:
- return False
- return p.val==q.val and self.check(p.left, q.right) and self.check(p.right, q.left)

下面的方法更容易理解
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def isSymmetric(self, root):
- """
- :type root: TreeNode
- :rtype: bool
- """
- # 递归,左右同时开始,结构一样就继续往下,不一样就返回false
- # 层遍历
- # 或者分成左右两个树,每一步都同时往下深度优先搜索
- if not root:
- return True
- def dfs(left,right):
- # 递归的终止条件是两个节点都为空
- if not (left or right):
- return True
- # 或者两个节点中有一个为空
- if not (left and right):
- return False
- # 或者两个节点的值不相等
- if left.val!=right.val:
- return False
- return dfs(left.left,right.right) and dfs(left.right,right.left)
- # 用递归函数,比较左节点,右节点
- return dfs(root.left,root.right)

用队列做
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def isSymmetric(self, root):
- """
- :type root: TreeNode
- :rtype: bool
- """
- # 队列实现
- queue = [root.left, root.right]
- while queue:
- # pop(0)是从头弹出,pop()是从尾弹出
- left = queue.pop(0)
- right = queue.pop(0)
- # 如果都是None,继续循环
- if not (left or right):
- continue
- # 如果其中一个是None
- if not (left and right):
- return False
- if left.val != right.val:
- return False
- queue.append(left.left)
- queue.append(right.right)
- queue.append(left.right)
- queue.append(right.left)
- return True

给你一棵二叉树的根节点,返回该树的 直径 。
二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。
两节点之间路径的 长度 由它们之间边数表示。
示例 1:

输入:root = [1,2,3,4,5] 输出:3 解释:3 ,取路径 [4,2,1,3] 或 [5,2,1,3] 的长度。
心得:想到了怎么来求,但就是不会写。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def diameterOfBinaryTree(self, root):
- """
- :type root: TreeNode
- :rtype: int
- """
- if root.left==None and root.right==None:
- return 0
- # 左右两边可以分开算
- # 直径等于左子树直径加右子树直径
- # 选出最大的
- # 父节点的直径等于左右子树中最大直径的边相加
- self.max_depth = 1
- def depth(node):
- if node == None:
- return 0
- L = depth(node.left)
- R = depth(node.right)
- deep = L + R
- self.max_depth = max(deep, self.max_depth)
-
- return max(L, R) + 1
-
- depth(root)
-
- return self.max_depth

心得:二叉树必须要熟练掌握BFS和DFS,几乎所有题都会用到,DFS主要就是递归,BFS主要就是队列维护节点。不断弹出和入队。
第一个有问题的地方就是数组需要==[],而不是None。
第二个地方是store数组需要及时清零。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def levelOrder(self, root):
- """
- :type root: TreeNode
- :rtype: List[List[int]]
- """
- if root == None:
- return []
- # 层序遍历用迭代,迭代用栈或队列
- # 广度优先搜索, BFS加一个层序
- result = []
- queue = []
- queue.append(root)
- store = []
- temp2 = []
- while queue != []:
- temp = queue.pop(0)
- store.append(temp.val)
- if temp.left != None:
- temp2.append(temp.left)
- if temp.right != None:
- temp2.append(temp.right)
- if queue == []:
- result.append(store)
- store = []
- queue = temp2
- temp2 = []
- return result

- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def sortedArrayToBST(self, nums):
- """
- :type nums: List[int]
- :rtype: TreeNode
- """
- # 递归
- length = len(nums)
- if length == 1:
- return TreeNode(nums[0])
- self.steam = None
- def dfs(nums):
- length = len(nums)
- if length == 1:
- return TreeNode(nums[0])
- mid = nums[length/2]
- left = nums[:length/2]
- L = dfs(left)
- R = None
- if length/2+1 < length:
- right = nums[length/2+1:]
- R = dfs(right)
- self.steam = TreeNode(mid, L, R)
- return self.steam
-
- dfs(nums)
-
- return self.steam

心得:方法还是很容易想到的,至于遍历方法有递归、迭代、队列,需要自己想一下哪种合适,然后写出每种方法对应的基础框架,在上面进行修改,带入到最左下角的节点,主要考虑终止条件、需要左右子树返回的值,result的填入顺序。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def isValidBST(self, root):
- """
- :type root: TreeNode
- :rtype: bool
- """
- # 遍历二叉树,从最左下的点开始遍历,最后数组是绝对升序的
- # 用dfs试试
- result = []
- def dfs(root):
- if root == None:
- return
- dfs(root.left)
- result.append(root.val)
- dfs(root.right)
- return
-
- dfs(root)
- for i in range(1,len(result)):
- if result[i-1] < result[i]:
- continue
- else:
- return False
-
- return True

心得:看了解析,直接递归,每个子树判断一下是否大于下限小于上限即可,并且上下限是实时更新的。这种返回True和False的题最好把递归放到return里面,这样一旦有一个false就能马上弹出递归,很方便。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def isValidBST(self, root):
- """
- :type root: TreeNode
- :rtype: bool
- """
- # 遍历二叉树,从最左下的点开始遍历,最后数组是绝对升序的
- # 用dfs试试
- flag = True
- def helper(root, upper = float('inf'), lower = float('-inf')):
- if root == None:
- return True
- if not (root.val < upper and root.val > lower):
- return False
- return helper(root.left, upper=root.val, lower=lower) and helper(root.right, upper=upper, lower=root.val)
-
- flag = helper(root)
-
- return flag

- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def kthSmallest(self, root, k):
- """
- :type root: TreeNode
- :type k: int
- :rtype: int
- """
- # 首先想到的肯定是遍历打印,然后选出第k个,但是那样效率太低
- # 先找到最小的值,然后慢慢返回查找第k个,中序遍历
- num = 0
- self.result = 0
- def dfs(root, num):
- if root == None:
- return num
- if num == k:
- self.result = root.val
- return num + 1
- temp = dfs(root.left, num)
- if temp == k:
- return k
- num = temp + 1
- if num == k:
- self.result = root.val
- return num + 1
- temp = dfs(root.right, num)
- if temp == k:
- return k
-
- return temp
-
- dfs(root, num)
-
- return self.result

用迭代法节省时间,遇到了等于k的就可以结束程序。要熟练掌握迭代法前中后序遍历。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def kthSmallest(self, root, k):
- """
- :type root: TreeNode
- :type k: int
- :rtype: int
- """
- # 首先想到的肯定是遍历打印,然后选出第k个,但是那样效率太低
- # 先找到最小的值,然后慢慢返回查找第k个,中序遍历
- # 用迭代的方法可以不用遍历整个二叉树
- stack = []
- target = 0
- result = 0
- while root or stack:
- if root:
- stack.append(root)
- root = root.left
- else:
- temp = stack.pop()
- target += 1
- if target == k:
- result = temp.val
- break
- root = temp.right
-
- return result

可以用BFS,层序遍历,从左到右遍历存储每层最后一个节点,也可以从右到左,存储每层第一个节点。
可以用DFS,从右开始向下遍历,记录深度,从左子树的时候超过深度就添加到结果中。
两种方法都想到了,但是DFS没写出来,BFS相对简单,写出来了。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def rightSideView(self, root):
- """
- :type root: TreeNode
- :rtype: List[int]
- """
- # 相当于先从右走,如果右不存在再从左走
- # 如果右子树走到头了,左子树比右子树深
- # 则再从左往下走,所以两颗子树应该同时走
- # 层遍历,只保存最右边的
- if root == None:
- return None
- result = []
- result.append(root.val)
- queue = []
- queue.append(root)
- temp2 = []
- store = []
- while queue != []:
- temp = queue.pop(0)
- if temp.right:
- temp2.append(temp.right)
- if temp.left:
- temp2.append(temp.left)
- if queue == []:
- if temp2 != []:
- result.append(temp2[0].val)
- queue = temp2
- temp2 = []
-
- return result

给你二叉树的根结点 root ,请你将它展开为一个单链表:
TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。示例 1:

输入:root = [1,2,5,3,4,null,6] 输出:[1,null,2,null,3,null,4,null,5,null,6]
心得:太蠢了,应该想到的,一直想不到怎么使5接到4后面,只需要用前序遍历,维护好子树返回上来的地址就行了。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def flatten(self, root):
- """
- :type root: TreeNode
- :rtype: None Do not return anything, modify root in-place instead.
- """
- # 前序遍历
- # DFS,递归或者迭代
- def dfs(root, result):
- if not root:
- return None
- result.append(root)
- dfs(root.left, result)
- dfs(root.right, result)
-
- result = []
- dfs(root, result)
- for i in range(len(result)-1):
- result[i].right = result[i+1]
- result[i].left = None
-
- return root

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
心得:递归!!
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def buildTree(self, preorder, inorder):
- """
- :type preorder: List[int]
- :type inorder: List[int]
- :rtype: TreeNode
- """
- # 前序遍历中,第一个数一定是根节点
- # 中序遍历中,根节点对应val左边的数就是左子树,右边的是右子树
- # 递归
- def dfs(preorder, inorder):
- if len(preorder) == 0:
- return None
- num = preorder.pop(0)
- root = TreeNode(num)
- ind = inorder.index(num)
- left = inorder[:ind]
- right = inorder[ind+1:]
- root.left = dfs(preorder[:len(left)], left)
- root.right = dfs(preorder[len(left):], right)
-
- return root
-
- return dfs(preorder, inorder)

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例 1:

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 输出:3 解释:和等于 8 的路径有 3 条,如图所示。
心得:想用一个数组把每个往下的路径的点存起来,遍历得出有多少条,试一下,果然超时。
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution(object):
- def pathSum(self, root, targetSum):
- """
- :type root: TreeNode
- :type targetSum: int
- :rtype: int
- """
- # dfs前序遍历
- self.count = 0
- self.depth = 0
- def dfs(root, store):
- if not root:
- return None
- self.depth += 1
- deep = self.depth
- store.append(root.val)
- num = 0
-
- for i in range(len(store)):
- for j in range(i,len(store)):
- num += store[j]
- if num == targetSum:
- self.count += 1
- num = 0
- temp = dfs(root.left, store)
- if temp:
- store = store[:deep]
- dfs(root.right, store)
- self.depth = deep-1
-
- return root
-
- store = []
- dfs(root, store)
-
- return self.count
暴力存储
- # Definition for a binary tree node.
- # class TreeNode(object):
- # def __init__(self, x):
- # self.val = x
- # self.left = None
- # self.right = None
-
- class Solution(object):
- def lowestCommonAncestor(self, root, p, q):
- """
- :type root: TreeNode
- :type p: TreeNode
- :type q: TreeNode
- :rtype: TreeNode
- """
- # DFS, 用栈的方式迭代
- stack = []
- stack.append(root)
- store = []
- store2 = []
- store3 = []
- depth = 0
- while stack or root:
- if store == [] or store2 == []:
- if root:
- stack.append(root)
- stack.append(root)
- if root == p:
- store = copy.deepcopy(stack)
- if root == q:
- store2 = copy.deepcopy(stack)
-
- root = root.left
- else:
- temp = stack.pop()
- root = temp.right
- else:
- break
-
- a = len(store)
- b = len(store2)
- for i in reversed(range(a)):
- for j in reversed(range(b)):
- if store[i].val == store2[j].val:
- return store[i]
