# @File : 199.py # @Description : # @Software: PyCharm """二叉树的右视图 关键字: 层序遍历 思路: 1、每次只取当前层的最后一个节点 """ from utils import TreeNode, createBiTree from typing import List class Solution: def rightSideView(self, root: TreeNode) -> List[int]: if not root: return [] q = [root] ret = [] while q: size = len(q) for i in range(size): cur = q.pop(0) if i + 1 == size: ret.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return ret print(Solution().rightSideView(createBiTree([1, 2, 3, None, 5, None, 4])))
# @File : 110.py # @Description : # @Software: PyCharm """平衡二叉树 关键字: 后序遍历 思路: 1、定义法: 验证左右孩子的深度差是否大于1 """ from utils import TreeNode, createBiTree class Solution: def isBalanced(self, root: TreeNode) -> bool: flag = True def dfs(root): if not root: return 0 left = dfs(root.left) right = dfs(root.right) if abs(right - left) > 1: nonlocal flag flag = False return max(left, right) + 1 dfs(root) return flag print(Solution().isBalanced(createBiTree([1, 2, 3, 4, 5, None, None, 8])))
def isCousins(self, root: TreeNode, x: int, y: int) -> bool: q = [root] if root.val in [x, y]: return False while q: size = len(q) count = 0 for i in range(size): cnt = 0 cur = q.pop(0) if cur.left: if cur.left.val in [x, y]: count += 1 cnt += 1 q.append(cur.left) if cur.right: if cur.right.val in [x, y]: count += 1 cnt += 1 q.append(cur.right) if cnt == 2: return False if count == 1: return False if count == 2: return True return False print(Solution().isCousins(createBiTree([1, 2, 3, None, 4, None, 5]), 5, 4))
""" from utils import TreeNode, createBiTree from typing import List class Solution: def verticalTraversal(self, root: TreeNode) -> List[List[int]]: box = [] def dfs(root, x, y): if not root: return box.append((x, y, root.val)) dfs(root.left, x - 1, y + 1) dfs(root.right, x + 1, y + 1) dfs(root, 0, 0) ret = [] last_x = None for x, y, value in sorted(box): if last_x is None or last_x != x: ret.append([]) ret[-1].append(value) last_x = x return ret print(Solution().verticalTraversal(createBiTree([3, 9, 20, None, None, 15, 7])))
# @Description : # @Software: PyCharm """二叉树的层序遍历 关键字: BFS、层次遍历 目标: 返回包含每层节点值的嵌套列表 思路: 分层处理 """ from utils import TreeNode, createBiTree from typing import List class Solution: def levelOrder(self, root: TreeNode) -> List[List[int]]: ret = [] if not root: return ret q = [root] while q: size = len(q) curs = [] for i in range(size): cur = q.pop(0) curs.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) ret.append(curs) return ret print(Solution().levelOrder(createBiTree([3, 9, 20, None, None, 15, 7])))
# @Time : 2020/10/10 9:28 # @Author : LiuBin # @File : 104.py # @Description : # @Software: PyCharm """二叉树的最大深度 关键字:后序遍历、分治 目标:获得从根节点到最远的叶子结点的节点数 思路: 1、获得左子树的最大深度;获得右子树的最大深度 2、返回左/右子树的最大的深度 + 1(自己贡献了1个深度) """ from utils import TreeNode, createBiTree class Solution: def maxDepth(self, root: TreeNode) -> int: if not root: return 0 left_max_depth = self.maxDepth(root.left) right_max_depth = self.maxDepth(root.right) return max(left_max_depth, right_max_depth) + 1 print(Solution().maxDepth(createBiTree([3, 9, 20, None, None, 15, 7])))
def findMode(self, root: TreeNode) -> List[int]: count = -1 mode, mode_cnt = [], 0 pre = None def dfs(root): if not root: return dfs(root.left) nonlocal count, pre, mode, mode_cnt if pre and pre.val == root.val: count += 1 else: if count > mode_cnt: mode, mode_cnt = [pre.val], count elif count == mode_cnt: mode.append(pre.val) count = 1 pre = root dfs(root.right) dfs(root) if count > mode_cnt: mode = [pre.val] elif count == mode_cnt: mode.append(pre.val) return mode print(Solution().findMode(createBiTree([1, 1, 2, None, None, 2])))
# @Time : 2020/10/20 12:37 # @Author : LiuBin # @File : 538.py # @Description : # @Software: PyCharm """把二叉搜索树转换为累加树 关键字: 中序遍历 思路: 1、先右孩子、再左孩子 2、输入 当前状态作为入参,返回处理后的状态 """ from utils import TreeNode, createBiTree class Solution: def convertBST(self, root: TreeNode) -> TreeNode: def dfs(root, sum): if not root: return sum sum = dfs(root.right, sum) root.val += sum sum = dfs(root.left, root.val) return sum dfs(root, 0) return root print(Solution().convertBST(createBiTree([4, 1, 6, 0, 2, 5, 7, None, None, None, 3, None, None, None, 8])))
# @Time : 2020/10/14 16:37 # @Author : LiuBin # @File : 235.py # @Description : # @Software: PyCharm """二叉搜索树的最近公共祖先 关键字: 前序遍历 """ from utils import TreeNode, createBiTree class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p, q) -> 'TreeNode': if p.val <= root.val <= q.val or q.val <= root.val <= p.val: return root if p.val < root.val: return self.lowestCommonAncestor(root.left, p, q) else: return self.lowestCommonAncestor(root.right, p, q) print(Solution().lowestCommonAncestor(createBiTree([6, 2, 8, 0, 4, 7, 9, None, None, 3, 5]), TreeNode(2), TreeNode(8)))
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: ret = [] def dfs(root, sum, path): if not root: if sum == 0: ret.append(path[:]) elif root.left and root.right: sum -= root.val path.append(root.val) dfs(root.left, sum, path) dfs(root.right, sum, path) path.pop() else: sum -= root.val path.append(root.val) if root.left: dfs(root.left, sum, path) else: dfs(root.right, sum, path) path.pop() if not root: return [] dfs(root, sum, []) return ret print(Solution().pathSum( createBiTree([5, 4, 8, 11, None, 13, 4, 7, 2, None, None, 5, 1]), 22))
# @File : 563.py # @Description : # @Software: PyCharm """二叉树的坡度 关键字: 后序遍历 思路: 1、维护左右子树的和 2、累加当前节点的坡度 """ from utils import TreeNode, createBiTree class Solution: def findTilt(self, root: TreeNode) -> int: total_slope = 0 def dfs(root): if not root: return 0 l_sum = dfs(root.left) r_sum = dfs(root.right) nonlocal total_slope total_slope += abs(l_sum - r_sum) return l_sum + root.val + r_sum dfs(root) return total_slope print(Solution().findTilt(createBiTree([1, 2, 3, 4, 5])))
""" from utils import TreeNode, createBiTree from typing import List class Solution: def findFrequentTreeSum(self, root: TreeNode) -> List[int]: d = {} max_ = 0 def dfs(root): if not root: return 0 sum = dfs(root.left) + root.val + dfs(root.right) if sum not in d: d[sum] = 0 d[sum] += 1 nonlocal max_ max_ = max(d[sum], max_) return sum dfs(root) ret = [] for k, v in d.items(): if v == max_: ret.append(k) return ret print(Solution().findFrequentTreeSum(createBiTree([5, 2, -3])))
# @Description : # @Software: PyCharm """路径总和 关键字: 先序遍历 思路: 1、有一个特殊情况,就是给定的树是空树,且sum是0,需要返回False(题目限制)。 2、自顶向下缩小问题范围,sum -= root.val,最后到空节点应该等于0,否则分别继续向下探索 """ from utils import TreeNode, createBiTree class Solution: def hasPathSum(self, root: TreeNode, sum: int) -> bool: def dfs(root, sum): if not root: # 此时必须保证是叶子节点 return sum == 0 elif root.right and root.left: sum -= root.val return dfs(root.left, sum) or dfs(root.right, sum) else: sum -= root.val return dfs(root.left, sum) if root.left else dfs( root.right, sum) if not root: return False return dfs(root, sum) print(Solution().hasPathSum(createBiTree([-2, None, -3]), -5))
loc = [] for i in left_loc + right_loc: s += 10**i * root.val loc.append(i + 1) return s + left_sum + right_sum, loc s, _ = dfs(root) return s def sumNumbers(self, root: TreeNode) -> int: ret = 0 if not root: return 0 def helper(path, node): nonlocal ret if not node.left and not node.right: ret += int(path) return if node.left: helper(path + str(node.left.val), node.left) if node.right: helper(path + str(node.right.val), node.right) helper(str(root.val), root) return ret print(Solution().sumNumbers(createBiTree([4, 9, 0, 5, 1])))
# @File : 513.py # @Description : # @Software: PyCharm """找树左下角的值 关键字: 中序遍历 思路: 1、一旦进入更深层的树,更新第一个该深度遍历的节点即可 """ from utils import TreeNode, createBiTree class Solution: def findBottomLeftValue(self, root: TreeNode): ret, dep = None, 0 def dfs(root, depth): if not root: return dfs(root.left, depth + 1) nonlocal ret, dep if depth > dep: ret, dep = root.val, depth dfs(root.right, depth + 1) dfs(root, 1) return ret print(Solution().findBottomLeftValue( createBiTree([1, 2, 3, 4, 5, 6, None, None, 7])))
""" from utils import TreeNode, createBiTree from typing import List class Solution: def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]: if not root: return [] q = [root] ret = [] depth = 1 while q: size = len(q) if len(ret) < depth: ret.append([]) for i in range(size): cur = q.pop(0) if depth % 2 == 1: ret[depth - 1].append(cur.val) else: ret[depth - 1].insert(0, cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) depth += 1 return ret print(Solution().zigzagLevelOrder(createBiTree([1, 2, None, 3, None, 4, 5])))
from utils import TreeNode, createBiTree class Solution: def recoverTree(self, root: TreeNode) -> None: """ Do not return anything, modify root in-place instead. """ pre = s = t = None def dfs(root): if not root: return dfs(root.left) nonlocal s, t, pre if pre and pre.val > root.val: s = pre if not s else s t = root pre = root dfs(root.right) dfs(root) s.val, t.val = t.val, s.val root = createBiTree( [68, 41, None, -85, None, -73, -49, -98, None, None, None, -124]) print(root) Solution().recoverTree(root) print(root)
# @Time : 2020/10/10 14:09 # @Author : LiuBin # @File : 101.py # @Description : # @Software: PyCharm """对称二叉树 关键字: 反向先序遍历 目标: 验证一颗二叉树是不是镜面对称的二叉树 思路: 1、对同一棵树同时使用先序遍历 2、先序遍历的方向相反,一个先访问左孩子,然后右孩子,一个先访问右孩子,然后左孩子 3、这样的先序遍历的路径是镜像对称的,比较两个节点是否一样 """ from utils import TreeNode, createBiTree class Solution: def isSymmetric(self, root: TreeNode) -> bool: def dfs(root1, root2): if not root1 and not root2: return True if root1 and root2 and root1.val == root2.val: return dfs(root1.left, root2.right) and dfs( root1.right, root2.left) return False return dfs(root, root) print(Solution().isSymmetric(createBiTree([1, 2, 2, None, 3, 3])))
# @Description : # @Software: PyCharm """二叉树的所有路径 关键字: 先序遍历 思路: 1、记录访问的路径 2、最后一步删除最前面的箭头 """ from utils import TreeNode, createBiTree from typing import List class Solution: def binaryTreePaths(self, root: TreeNode) -> List[str]: ret = [] if not root: return [] def dfs(root, path): if not root.left and not root.right: ret.append((path + "->" + str(root.val))[2:]) return if root.left: dfs(root.left, path + "->" + str(root.val)) if root.right: dfs(root.right, path + "->" + str(root.val)) dfs(root, "") return ret print(Solution().binaryTreePaths(createBiTree([1])))
# @Time : 2020/10/10 14:03 # @Author : LiuBin # @File : 100.py # @Description : # @Software: PyCharm """相同的树 关键字: 先序遍历 思路: 1、同时遍历,同时比较两个节点 """ from utils import TreeNode, createBiTree class Solution: def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: if not p and not q: return True if p and q and p.val == q.val: return self.isSameTree(p.left, q.left) and self.isSameTree( p.right, q.right) return False a = createBiTree([1, None, 3, 2]) b = createBiTree([1, None, 3]) print(Solution().isSameTree(a, b))
# @Software: PyCharm """ 在每个树行中找最大值 关键字: 任何遍历 思路: 1、维护每行的最大值数组,深度对应索引 """ from utils import TreeNode, createBiTree from typing import List class Solution: def largestValues(self, root: TreeNode) -> List[int]: ret = [] def dfs(root, depth): if not root: return nonlocal ret if len(ret) <= depth: ret.append(root.val) else: ret[depth] = max(ret[depth], root.val) dfs(root.left, depth + 1) dfs(root.right, depth + 1) dfs(root, 0) return ret print(Solution().largestValues(createBiTree([1, 3, 2, 5, 3, None, 9])))
def isValidBSTByInOrder(self, root: TreeNode) -> bool: def dfs(root): if not root: return if self.flag: dfs(root.left) if self.pre is not None and self.pre >= root.val: self.flag = False else: self.pre = root.val if self.flag: dfs(root.right) dfs(root) return self.flag def isValidBST(self, root: TreeNode) -> bool: def dfs(root, min_=float('-inf'), max_=float('inf')): if not root: return True if min_ >= root.val or max_ <= root.val or not dfs( root.left, min_, root.val) or not dfs( root.right, root.val, max_): return False return True return dfs(root) print(Solution().isValidBST(createBiTree([1, 1])))
# @Author : LiuBin # @File : 662.py # @Description : # @Software: PyCharm """二叉树最大宽度 关键字: 中序遍历 """ from utils import TreeNode, createBiTree class Solution: def widthOfBinaryTree(self, root: TreeNode) -> int: if not root: return 0 q = [(root, 1)] width = 1 while q: size = len(q) if size > 1: (s_root, s_no), (e_root, e_no) = q[0], q[-1] width = max(width, e_no - s_no + 1) for i in range(size): cur, no = q.pop(0) if cur.left: q.append((cur.left, no * 2 - 1)) if cur.right: q.append((cur.right, no * 2)) return width print(Solution().widthOfBinaryTree( createBiTree([1, 3, 2, 5, None, None, 9, 6, None, None, 7])))
# @Time : 2020/10/14 17:40 # @Author : LiuBin # @File : 236.py # @Description : # @Software: PyCharm """二叉树的最近公共祖先 关键字: 后序遍历 思路: 1、遇到直接返回找到的目标节点 2、如果左右子树各贡献了节点,那么最早遇到的父节点就是公共祖先 3、如果只有一个子树贡献节点,那么属于目标节点本身即是公共祖先。 """ from utils import TreeNode, createBiTree class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root or root == q or root == p: return root l = self.lowestCommonAncestor(root.left, p, q) r = self.lowestCommonAncestor(root.right, p, q) if not l: return r if not r: return l return root a = Solution().lowestCommonAncestor( createBiTree([-1, 0, 3, -2, 4, None, None, 8]), TreeNode(8), TreeNode(4)) print(a)
from utils import TreeNode, createBiTree class Solution: def flatten(self, root: TreeNode) -> None: """ Do not return anything, modify root in-place instead. """ pre = None def dfs(root, parent): if not root: return dfs(root.right, root) dfs(root.left, root) nonlocal pre if parent: root.right = pre if parent.left is root: parent.left = None parent.right = root pre = root dfs(root, None) root = createBiTree([3, 2]) Solution().flatten(root) print(root)
return 0 return self.countNodesByDFS(root.left) + self.countNodesByDFS( root.right) + 1 def countNodes(self, root: TreeNode) -> int: def dfs_left(root): if not root: return 0 return dfs_left(root.left) + 1 if not root: return 0 depth = dfs_left(root) res = 0 def dfs_right(root, curdep, idx): nonlocal depth, res if not root: return 0 if curdep == depth: res = idx if not res: dfs_right(root.right, curdep + 1, 2 * idx + 1) if not res: dfs_right(root.left, curdep + 1, 2 * idx) dfs_right(root, 1, 1) return res print(Solution().countNodes(createBiTree([1, 2, 3, 4, 5, 6, 7])))
关键字: 中序遍历 思路: 1、获得有序数列 2、维护最小的前后元素的差值 """ from utils import TreeNode, createBiTree class Solution: def getMinimumDifference(self, root: TreeNode): min_ = None last_val = None def dfs(root): if not root: return dfs(root.left) nonlocal min_, last_val if last_val is not None: if not min_ or root.val - last_val < min_: min_ = root.val - last_val last_val = root.val dfs(root.right) dfs(root) return min_ print(Solution().getMinimumDifference(createBiTree([1, None, 5, 3])))
# @Time : 2020/10/15 16:00 # @Author : LiuBin # @File : 226.py # @Description : # @Software: PyCharm """翻转二叉树 关键字: 后序遍历 """ from utils import TreeNode, createBiTree class Solution: def invertTree(self, root: TreeNode) -> TreeNode: if not root: return root.left, root.right = self.invertTree(root.right), self.invertTree(root.left) return root print(Solution().invertTree(createBiTree([1, 2, 3])))