递归 树的高度 力扣地址
题目描述 给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例: 给定二叉树 [3,9,20,null,null,15,7]
,
返回它的最大深度 3 。
题目解答 比较简单。。dfs
1 2 3 4 5 6 7 8 9 10 11 12 13 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def maxDepth (self, root: TreeNode ) -> int: if root is None : return 0 return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public int maxDepth (TreeNode root) { if (root == null ) return 0 ; return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1 ; } }
平衡树 力扣地址
题目描述 给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
返回 true
。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false
。
题目解答 用递归计算树的高度,如果返回-1代表树不平衡。即在上一题的函数中加个判断树平衡与否的条件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def isBalanced (self, root: TreeNode ) -> bool: return self.height(root) >= 0 def height (self, root: TreeNode ): if root is None : return 0 a = self.height(root.left) b = self.height(root.right) if a >= 0 and b >= 0 and abs(a - b) <= 1 : return max(a, b) + 1 else : return -1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public boolean isBalanced (TreeNode root) { return height(root) >= 0 ; } public int height (TreeNode root) { if (root == null ){ return 0 ; } int a = height(root.left); int b = height(root.right); if (a >= 0 && b >= 0 && Math.abs(a-b) <= 1 ){ return Math.max(a,b) + 1 ; } else return -1 ; } }
二叉树的直径 力扣地址
题目描述 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
示例 : 给定二叉树
1
/ \
2 3
/ \
4 5
返回 3 , 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
题目解答 递归,返回每个节点左右节点的之树长度的最大值,最大长度应该设置为公共变量,与每个节点左右最大长度之和比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : maxHeight = 0 def diameterOfBinaryTree (self, root: TreeNode ) -> int: if root is None : return 0 self.dfs(root) return self.maxHeight def dfs (self, root: TreeNode ): if root.left is None and root.right is None : return 0 leftHeight = 0 if root.left is None else self.dfs(root.left) + 1 rightHeight = 0 if root.right is None else self.dfs(root.right) + 1 self.maxHeight = max(self.maxHeight, leftHeight + rightHeight) return max(leftHeight, rightHeight)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { int maxHeight = 0 ; public int diameterOfBinaryTree (TreeNode root) { if (root == null ){ return 0 ; } dfs(root); return maxHeight; } public int dfs (TreeNode root) { if (root.left == null && root.right == null ) return 0 ; int leftHeight = root.left == null ? 0 :dfs(root.left)+1 ; int rightHeight = root.right == null ? 0 :dfs(root.right)+1 ; maxHeight = Math.max(maxHeight,leftHeight + rightHeight); return Math.max(leftHeight,rightHeight); } }
翻转二叉树 力扣地址
题目描述 翻转一棵二叉树。
示例:
输入:
1 2 3 4 5 4 / \ 2 7 / \ / \ 1 3 6 9
输出:
1 2 3 4 5 4 / \ 7 2 / \ / \ 9 6 3 1
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def invertTree (self, root: TreeNode ) -> TreeNode: self.reverse(root) return root def reverse (self,root:TreeNode ): if root is None : return a = root.right root.right = root.left root.left = a self.reverse(root.left) self.reverse(root.right)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public TreeNode invertTree (TreeNode root) { if (root == null ) return null ; TreeNode left = root.left; root.left = invertTree(root.right); root.right = invertTree(left); return root; } }
合并二叉树 力扣地址
题目描述 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 输入: Tree 1 Tree 2 1 2 / \ / \ 3 2 1 3 / \ \ 5 4 7 输出: 合并后的树: 3 / \ 4 5 / \ \ 5 4 7
注意: 合并必须从两个树的根节点开始。
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def mergeTrees (self, t1: TreeNode, t2: TreeNode ) -> TreeNode: if t1 is None and t2 is None : return None if t1 is None : return t2 if t2 is None : return t1 root = TreeNode(None ) root.val = t1.val + t2.val root.left = self.mergeTrees(t1.left, t2.left) root.right = self.mergeTrees(t1.right, t2.right) return root
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public TreeNode mergeTrees (TreeNode t1, TreeNode t2) { if (t1 == null && t2 == null ) return null ; if (t1 == null ) return t2; if (t2 == null ) return t1; TreeNode root = new TreeNode(); root.val = t1.val + t2.val; root.left = mergeTrees(t1.left, t2.left); root.right = mergeTrees(t1.right, t2.right); return root; } }
路径总和 力扣地址
题目描述 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例: 给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
返回 true
, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2
。
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def hasPathSum (self, root: TreeNode, sum: int ) -> bool: if root is None : return False if root.left is None and root.right is None and root.val == sum: return True return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public boolean hasPathSum (TreeNode root, int sum) { if (root == null ) return false ; if (root.left == null && root.right == null && root.val == sum) return true ; return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); } }
路径总和Ⅲ 力扣地址
题目描述 给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 返回 3。和等于 8 的路径有: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11
题目解答 这道题需要双重递归,第一层递归选择开始节点,第二层递归向下遍历求得路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class TreeNode : def __init__ (self, val=0 , left=None, right=None ): self.val = val self.left = left self.right = right class Solution : def pathSum (self, root: TreeNode, sum: int ) -> int: if root is None : return 0 valueNum = self.dfs(root,sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum) return valueNum def dfs (self,root:TreeNode,sum ): if root is None : return 0 num = 0 if root.val == sum: num += 1 num = num + self.dfs(root.left,sum - root.val) + self.dfs(root.right,sum - root.val) return num
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public int pathSum (TreeNode root, int sum) { if (root == null ) return 0 ; int ret = pathSumStartWithRoot(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum); return ret; } private int pathSumStartWithRoot (TreeNode root, int sum) { if (root == null ) return 0 ; int ret = 0 ; if (root.val == sum) ret++; ret += pathSumStartWithRoot(root.left, sum - root.val) + pathSumStartWithRoot(root.right, sum - root.val); return ret; }
另一个树的子树 力扣地址
题目描述 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
示例 1: 给定的树 s:
给定的树 t:
返回 true ,因为 t 与 s 的一个子树拥有相同的结构和节点值。
示例 2: 给定的树 s:
1 2 3 4 5 6 7 3 / \ 4 5 / \ 1 2 / 0
给定的树 t:
返回 false 。
题目解答 和上一题类似,第一层递归判断开始的节点,第二层判断路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class TreeNode : def __init__ (self, val=0 , left=None, right=None ): self.val = val self.left = left self.right = right class Solution : def isSubtree (self, s: TreeNode, t: TreeNode ) -> bool: if s is None : return False return self.dfs(s, t) or self.isSubtree(s.left, t) or self.isSubtree(s.right, t) def dfs (self, s: TreeNode, t: TreeNode ): if s is None and t is None : return True if s is None or t is None : return False if s.val != t.val: return False return self.dfs(s.left, t.left) and self.dfs(s.right, t.right)
1 2 3 4 5 6 7 8 9 10 11 public boolean isSubtree (TreeNode s, TreeNode t) { if (s == null ) return false ; return isSubtreeWithRoot(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t); } private boolean isSubtreeWithRoot (TreeNode s, TreeNode t) { if (t == null && s == null ) return true ; if (t == null || s == null ) return false ; if (t.val != s.val) return false ; return isSubtreeWithRoot(s.left, t.left) && isSubtreeWithRoot(s.right, t.right); }
对称二叉树 力扣地址
题目描述 给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3]
是对称的。
1 2 3 4 5 1 / \ 2 2 / \ / \ 3 4 4 3
但是下面这个 [1,2,2,null,3,null,3]
则不是镜像对称的:
题目解答 可以迭代,还是直接递归吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def isSymmetric (self, root: TreeNode ) -> bool: if root is None : return True return self.dfs(root.left, root.right) def dfs (self, l: TreeNode, r: TreeNode ): if l is None and r is None : return True if l is None or r is None : return False if l.val != r.val: return False return self.dfs(l.left, r.right) and self.dfs(l.right, r.left)
1 2 3 4 5 6 7 8 9 10 11 public boolean isSymmetric (TreeNode root) { if (root == null ) return true ; return isSymmetric(root.left, root.right); } private boolean isSymmetric (TreeNode t1, TreeNode t2) { if (t1 == null && t2 == null ) return true ; if (t1 == null || t2 == null ) return false ; if (t1.val != t2.val) return false ; return isSymmetric(t1.left, t2.right) && isSymmetric(t1.right, t2.left); }
二叉树的最小深度 力扣地址
题目描述 给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
返回它的最小深度 2.
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def minDepth (self, root: TreeNode ) -> int: if root is None : return 0 if root.left is None and root.right is None : return 1 if root.left is None or root.right is None : return self.minDepth(root.left if root.left is not None else root.right) + 1 return min(self.minDepth(root.left) + 1 , self.minDepth(root.right) + 1 )
1 2 3 4 5 6 7 public int minDepth (TreeNode root) { if (root == null ) return 0 ; int left = minDepth(root.left); int right = minDepth(root.right); if (left == 0 || right == 0 ) return left + right + 1 ; return Math.min(left, right) + 1 ; }
左叶子之和 力扣地址
题目描述 计算给定二叉树的所有左叶子之和。
示例:
1 2 3 4 5 6 7 3 / \ 9 20 / \ 15 7 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def sumOfLeftLeaves (self, root: TreeNode ) -> int: if root is None : return 0 sum = 0 if root.left is not None : if root.left.left is None and root.left.right is None : sum += root.left.val return sum + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
1 2 3 4 5 6 7 8 9 10 11 public int sumOfLeftLeaves (TreeNode root) { if (root == null ) return 0 ; if (isLeaf(root.left)) return root.left.val + sumOfLeftLeaves(root.right); return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right); } private boolean isLeaf (TreeNode node) { if (node == null ) return false ; return node.left == null && node.right == null ; }
最长同值路径 力扣地址
题目描述: 给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。
注意 :两个节点之间的路径长度由它们之间的边数表示。
示例 1:
输入:
5
/ \
4 5
/ \ \
1 1 5
输出:
示例 2:
输入:
1
/ \
4 5
/ \ \
4 4 5
输出:
注意: 给定的二叉树不超过10000个结点。 树的高度不超过1000。
题目解答 递归的返回值和要求的结果不同,需要设置一个全局变量。
递归的返回值应该是左右最大路径之一,要求的结果,与全局变量比较的是左右最大路径之和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def longestUnivaluePath (self, root: TreeNode ) -> int: self.maxPath = 0 def dfs (root: TreeNode ): if root is None : return 0 left = dfs(root.left) right = dfs(root.right) leftPath = left + 1 if root.left is not None and root.left.val == root.val else 0 rightPath = right + 1 if root.right is not None and root.right.val == root.val else 0 self.maxPath = max(self.maxPath, leftPath + rightPath) return max(leftPath, rightPath) dfs(root) return self.maxPath
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private int path = 0 ;public int longestUnivaluePath (TreeNode root) { dfs(root); return path; } private int dfs (TreeNode root) { if (root == null ) return 0 ; int left = dfs(root.left); int right = dfs(root.right); int leftPath = root.left != null && root.left.val == root.val ? left + 1 : 0 ; int rightPath = root.right != null && root.right.val == root.val ? right + 1 : 0 ; path = Math.max(path, leftPath + rightPath); return Math.max(leftPath, rightPath); }
打家劫舍Ⅲ 力扣地址
题目描述 在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
示例 1:
输入: [3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
输出: 7
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例 2:
输入: [3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.
题目解答 关键点:判断当前节点偷与否
python 的提交会超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def rob (self, root: TreeNode ) -> int: """ 如果偷当前节点,则左右子节点都不能偷, 如果不偷当前节点,返回左右子节点的最大值 :param root: :return: """ if root is None : return 0 val1 = root.val if root.left is not None : val1 += self.rob(root.left.left) + self.rob(root.left.right) if root.right is not None : val1 += self.rob(root.right.left) + self.rob(root.right.right) val2 = self.rob(root.left) + self.rob(root.right) return max(val1, val2)
1 2 3 4 5 6 7 8 public int rob (TreeNode root) { if (root == null ) return 0 ; int val1 = root.val; if (root.left != null ) val1 += rob(root.left.left) + rob(root.left.right); if (root.right != null ) val1 += rob(root.right.left) + rob(root.right.right); int val2 = rob(root.left) + rob(root.right); return Math.max(val1, val2); }
二叉树中第二小的节点 力扣地址
题目描述 给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。
示例 1:
1 2 3 4 5 6 7 8 9 输入: 2 / \ 2 5 / \ 5 7 输出: 5 说明: 最小的值是 2 ,第二小的值是 5 。
示例 2:
1 2 3 4 5 6 7 输入: 2 / \ 2 2 输出: -1 说明: 最小的值是 2, 但是不存在第二小的值。
题目解答 用python的简单方法就是用set,因为set是取不重复值,在排序后取第二个值….
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def findSecondMinimumValue (self, root: TreeNode ) -> int: if root is None : return -1 if root.left is None and root.right is None : return -1 leftVal = root.left.val rightVal = root.right.val if root.val == root.left.val: leftVal = self.findSecondMinimumValue(root.left) if root.val == root.right.val: rightVal = self.findSecondMinimumValue(root.right) if leftVal != -1 and rightVal != -1 : return min(leftVal, rightVal) if leftVal == -1 : return rightVal return leftVal
1 2 3 4 5 6 7 8 9 10 11 public int findSecondMinimumValue (TreeNode root) { if (root == null ) return -1 ; if (root.left == null && root.right == null ) return -1 ; int leftVal = root.left.val; int rightVal = root.right.val; if (leftVal == root.val) leftVal = findSecondMinimumValue(root.left); if (rightVal == root.val) rightVal = findSecondMinimumValue(root.right); if (leftVal != -1 && rightVal != -1 ) return Math.min(leftVal, rightVal); if (leftVal != -1 ) return leftVal; return rightVal; }
层次遍历 二叉树的层次遍历参考小浩算法 )!
二叉树的层平均值 力扣地址
题目描述 给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
示例 1:
1 2 3 4 5 6 7 8 9 输入: 3 / \ 9 20 / \ 15 7 输出:[3, 14.5, 11] 解释: 第 0 层的平均值是 3 , 第1层是 14.5 , 第2层是 11 。因此返回 [3, 14.5, 11] 。
题目解答 采用队列的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import queuefrom typing import Listclass TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def averageOfLevels (self, root: TreeNode ) -> List[float]: treeQueue = queue.Queue() ave = [] if root is None : return 0 treeQueue.put(root) while treeQueue.qsize() > 0 : getNode = [] while treeQueue.qsize() > 0 : node = treeQueue.get() print(node.val) getNode.append(node) average = 0 for i in getNode: average += i.val if i.left is not None : treeQueue.put(i.left) if i.right is not None : treeQueue.put(i.right) average = average / len(getNode) ave.append(average) return ave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public List<Double> averageOfLevels (TreeNode root) { List<Double> ret = new ArrayList<>(); if (root == null ) return ret; Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { int cnt = queue.size(); double sum = 0 ; for (int i = 0 ; i < cnt; i++) { TreeNode node = queue.poll(); sum += node.val; if (node.left != null ) queue.add(node.left); if (node.right != null ) queue.add(node.right); } ret.add(sum / cnt); } return ret; }
找树左下角的值 力扣地址
题目描述 给定一个二叉树,在树的最后一行找到最左边的值。
示例 1:
1 2 3 4 5 6 7 8 输入: 2 / \ 1 3 输出: 1
示例 2:
输入:
1
/ \
2 3
/ / \
4 5 6
/
7
输出:
7
树根节点不为NULL
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def findBottomLeftValue (self, root: TreeNode ) -> int: queue = [root] res = [] while queue: cur = [] nxt = [] for node in queue: cur.append(node.val) if node.left: nxt.append(node.left) if node.right: nxt.append(node.right) queue = nxt return cur.pop(0 )
1 2 3 4 5 6 7 8 9 10 public int findBottomLeftValue (TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { root = queue.poll(); if (root.right != null ) queue.add(root.right); if (root.left != null ) queue.add(root.left); } return root.val; }
前中后序遍历(迭代实现) 使用栈
二叉树的前序遍历 力扣地址
题目描述 给定一个二叉树,返回它的 前序 遍历。
示例:
1 2 3 4 5 6 7 8 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3]
要求:使用迭代
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def preorderTraversal (self, root: TreeNode ) -> List[int]: stack = [] result = [] stack.append(root) while len(stack) > 0 : a = stack.pop() if not a: continue result.append(a.val) stack.append(a.right) stack.append(a.left) return result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public List<Integer> preorderTraversal (TreeNode root) { List<Integer> ret = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (node == null ) continue ; ret.add(node.val); stack.push(node.right); stack.push(node.left); } return ret; }
二叉树的后序遍历 力扣地址
题目描述 给定一个二叉树,返回它的 后序 遍历。
示例:
1 2 3 4 5 6 7 8 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1]
题目解答
python:增加一个pre节点,如果pre节点是栈顶节点的子节点且pre不为空或栈顶节点没有子节点时,栈顶节点出栈,pre更新为出栈节点;否则将栈顶节点的右节点和左节点分别入栈。
java:前序遍历为 root -> left -> right,后序遍历为 left -> right -> root。可以修改前序遍历成为 root -> right -> left,那么这个顺序就和后序遍历正好相反。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from typing import Listclass TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def postorderTraversal (self, root: TreeNode ) -> List[int]: if not root: return [] stack = [root] result = [] pre = None while len(stack) > 0 : a = stack[-1 ] print(1 ) if not a: continue if ((pre == a.right or pre == a.left) and pre is not None ) or (a.right is None and a.left is None ): stack.pop() result.append(a.val) pre = a else : if a.right is not None : stack.append(a.right) if a.left is not None : stack.append(a.left) return result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public List<Integer> postorderTraversal (TreeNode root) { List<Integer> ret = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode node = stack.pop(); if (node == null ) continue ; ret.add(node.val); stack.push(node.left); stack.push(node.right); } Collections.reverse(ret); return ret; }
二叉树的中序遍历 力扣地址
题目描述 给定一个二叉树,返回它的中序 遍历。
示例:
1 2 3 4 5 6 7 8 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2]
题目解答 发现一种python中很秒的写法,如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from typing import Listclass TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def inorderTraversal (self, root: TreeNode ) -> List[int]: stack, rel = [root], [] while stack: a = stack.pop() if isinstance(a, TreeNode): stack.extend([a.right, a.val, a.left]) elif isinstance(a, int): rel.append(a) return rel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public List<Integer> inorderTraversal (TreeNode root) { List<Integer> ret = new ArrayList<>(); if (root == null ) return ret; Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; while (cur != null || !stack.isEmpty()) { while (cur != null ) { stack.push(cur); cur = cur.left; } TreeNode node = stack.pop(); ret.add(node.val); cur = node.right; } return ret; }
二叉查找树 二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点。
二叉查找树中序遍历有序。
修建二叉查找树 力扣地址
题目描述 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 输入: 1 / \ 0 2 L = 1 R = 2 输出: 1 \ 2
示例 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 输入: 3 / \ 0 4 \ 2 / 1 L = 1 R = 3 输出: 3 / 2 / 1
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def trimBST (self, root: TreeNode, L: int, R: int ) -> TreeNode: if not root: return root if root.val < L: return self.trimBST(root.right, L, R) if root.val > R: return self.trimBST(root.left, L, R) root.left = self.trimBST(root.left, L, R) root.right = self.trimBST(root.right, L, R) return root
1 2 3 4 5 6 7 8 public TreeNode trimBST (TreeNode root, int L, int R) { if (root == null ) return null ; if (root.val > R) return trimBST(root.left, L, R); if (root.val < L) return trimBST(root.right, L, R); root.left = trimBST(root.left, L, R); root.right = trimBST(root.right, L, R); return root; }
二叉查找树中第k小的元素 力扣地址
题目描述 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明: 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:
1 2 3 4 5 6 7 输入: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2 输出: 1
示例 2:
1 2 3 4 5 6 7 8 9 输入: root = [5,3,6,2,4,null,null,1], k = 3 5 / \ 3 6 / \ 2 4 / 1 输出: 3
题目解答 二叉查找树的中序遍历是有序的,返回中序编列后的第k个元素即可。
优化是提前终止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class TreeNode : def __init__ (self, val=0 , left=None, right=None ): self.val = val self.left = left self.right = right class Solution : def kthSmallest (self, root: TreeNode, k: int ) -> int: stack, rel = [root], [] while stack: a = stack.pop() if isinstance(a, TreeNode): stack.extend([a.right, a.val, a.left]) elif isinstance(a, int): rel.append(a) return rel[k - 1 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private int cnt = 0 ;private int val;public int kthSmallest (TreeNode root, int k) { inOrder(root, k); return val; } private void inOrder (TreeNode node, int k) { if (node == null ) return ; inOrder(node.left, k); cnt++; if (cnt == k) { val = node.val; return ; } inOrder(node.right, k); }
把二叉搜索树转换为累加树 力扣地址
题目描述 给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
例如:
1 2 3 4 5 6 7 8 9 输入: 原始二叉搜索树: 5 / \ 2 13 输出: 转换为累加树: 18 / \ 20 13
题目解答 先便利右子树,再遍历左子树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def convertBST (self, root: TreeNode ) -> TreeNode: cur = 0 def dfs (root: TreeNode ): if not root: return nonlocal cur dfs(root.right) cur += root.val root.val = cur dfs(root.left) dfs(root) return root
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private int sum = 0 ;public TreeNode convertBST (TreeNode root) { traver(root); return root; } private void traver (TreeNode node) { if (node == null ) return ; traver(node.right); sum += node.val; node.val = sum; traver(node.left); }
二叉树搜索树的最近公共祖先 力扣地址
题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
1 2 3 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
1 2 3 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
题目解答 利用二叉搜索树的性质,如果p,q在当前节点同一侧,继续往下递归,如果在两侧,则返回当前节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def lowestCommonAncestor (self, root: TreeNode, p: TreeNode, q: TreeNode ) -> TreeNode: if root.val > p.val and root.val > q.val: return self.lowestCommonAncestor(root.left, p, q) if root.val < p.val and root.val < q.val: return self.lowestCommonAncestor(root.right, p, q) return root
1 2 3 4 5 public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) { if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q); if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q); return root; }
二叉树的最近公共祖先 力扣地址
题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
1 2 3 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
1 2 3 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
题目解答 如果搜到就p或者q就返回,如果左右都搜到就返回当前节点,如果左没有,就返回由,同理右没有就返回左。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def lowestCommonAncestor (self, root: TreeNode, p: TreeNode, q: TreeNode ) -> TreeNode: if not root or root == p or root == q: return root left = self.lowestCommonAncestor(root.left, p, q) right = self.lowestCommonAncestor(root.right, p, q) if left and right: return root if not left: return right return left
1 2 3 4 5 6 public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) { if (root == null || root == p || root == q) return root; TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); return left == null ? right : right == null ? left : root; }
将有序数组转换为二叉搜索树 力扣地址
题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
1 2 3 4 5 0 / \ -3 9 / / -10 5
题目解答 二叉搜索树的中序遍历是升序的,因此我们可以利用任一节点为根节点,数组左边为其左子树,右边为其右子树;因为题目要求高度平衡,所以选数组中间的为根节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from typing import Listclass TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def sortedArrayToBST (self, nums: List[int] ) -> TreeNode: root = self.dfs(nums, 0 , len(nums) - 1 ) return root def dfs (self, nums, start, last ): if start > last: return mid = (start + last) // 2 root = TreeNode(nums[mid]) root.left = self.dfs(nums, start, mid - 1 ) root.right = self.dfs(nums, mid + 1 , last) return root
1 2 3 4 5 6 7 8 9 10 11 12 public TreeNode sortedArrayToBST (int [] nums) { return toBST(nums, 0 , nums.length - 1 ); } private TreeNode toBST (int [] nums, int sIdx, int eIdx) { if (sIdx > eIdx) return null ; int mIdx = (sIdx + eIdx) / 2 ; TreeNode root = new TreeNode(nums[mIdx]); root.left = toBST(nums, sIdx, mIdx - 1 ); root.right = toBST(nums, mIdx + 1 , eIdx); return root; }
有序链表转换二叉搜索树 力扣地址
题目描述 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
1 2 3 4 5 6 7 8 9 给定的有序链表: [-10, -3, 0, 5, 9], 一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树: 0 / \ -3 9 / / -10 5
题目解答 与上一题类似,只是链表不能直接根据索引获取中间值,可以使用快慢指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class ListNode : def __init__ (self, val=0 , next=None ): self.val = val self.next = next class TreeNode : def __init__ (self, val=0 , left=None, right=None ): self.val = val self.left = left self.right = right class Solution : def sortedListToBST (self, head: ListNode ) -> TreeNode: root = self.dfs(head, None ) return root def dfs (self, head, tails ): if head == tails: return node = self.findMid(head, tails) root = TreeNode(node.val) root.left = self.dfs(head, node) root.right = self.dfs(node.next, tails) return root def findMid (self, head, tails ): slow, fast = head while fast != tails and fast.next != tails: slow = slow.next fast = fast.next.next return slow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public TreeNode sortedListToBST (ListNode head) { if (head == null ) return null ; if (head.next == null ) return new TreeNode(head.val); ListNode preMid = preMid(head); ListNode mid = preMid.next; preMid.next = null ; TreeNode t = new TreeNode(mid.val); t.left = sortedListToBST(head); t.right = sortedListToBST(mid.next); return t; } private ListNode preMid (ListNode head) { ListNode slow = head, fast = head.next; ListNode pre = head; while (fast != null && fast.next != null ) { pre = slow; slow = slow.next; fast = fast.next.next; } return pre; }
两数之和Ⅳ 力扣地址
题目描述 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。
案例 1:
1 2 3 4 5 6 7 8 9 10 输入: 5 / \ 3 6 / \ \ 2 4 7 Target = 9 输出: True
案例 2:
1 2 3 4 5 6 7 8 9 10 输入: 5 / \ 3 6 / \ \ 2 4 7 Target = 28 输出: False
题目解答 利用中序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def findTarget (self, root: TreeNode, k: int ) -> bool: list = [] def mid (root: TreeNode ): if root.left: mid(root.left) list.append(root.val) if root.right: mid(root.right) mid(root) for i in list: if k - i == i: continue elif (k - i) in list: return True return False
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public boolean findTarget (TreeNode root, int k) { List<Integer> nums = new ArrayList<>(); inOrder(root, nums); int i = 0 , j = nums.size() - 1 ; while (i < j) { int sum = nums.get(i) + nums.get(j); if (sum == k) return true ; if (sum < k) i++; else j--; } return false ; } private void inOrder (TreeNode root, List<Integer> nums) { if (root == null ) return ; inOrder(root.left, nums); nums.add(root.val); inOrder(root.right, nums); }
二叉搜索树的最小绝对差 力扣地址
题目描述 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 输入: 1 \ 3 / 2 输出: 1 解释: 最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。
题目解答 利用二叉搜索树的中序遍历有序性,计算相邻元素间的差的最小值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def getMinimumDifference (self, root: TreeNode ) -> int: list = [] def mid (root: TreeNode ): if root.left: mid(root.left) list.append(root.val) if root.right: mid(root.right) mid(root) min = 1000000 i = 0 j = 1 while j < len(list): if (list[j]-list[i]) < min: min = list[j] - list[i] j += 1 i += 1 return min
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private int minDiff = Integer.MAX_VALUE;private TreeNode preNode = null ;public int getMinimumDifference (TreeNode root) { inOrder(root); return minDiff; } private void inOrder (TreeNode node) { if (node == null ) return ; inOrder(node.left); if (preNode != null ) minDiff = Math.min(minDiff, node.val - preNode.val); preNode = node; inOrder(node.right); }
二叉搜索树中的众数 力扣地址
题目描述 给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
结点左子树中所含结点的值小于等于当前结点的值
结点右子树中所含结点的值大于等于当前结点的值
左子树和右子树都是二叉搜索树
例如: 给定 BST [1,null,2,2]
,
返回[2]
.
提示 :如果众数超过1个,不需考虑输出顺序
题目解答 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from typing import Listclass TreeNode : def __init__ (self, x ): self.val = x self.left = None self.right = None class Solution : def findMode (self, root: TreeNode ) -> List[int]: if not root: return [] stack = [root] dic = {} while stack: node = stack.pop() if node.val not in dic: dic[node.val] = 1 else : dic[node.val] += 1 if node.left: stack.append(node.left) if node.right: stack.append(node.right) max_values = max(dic.values()) list = [] for k, v in dic.items(): if v == max_values: list.append(k) return list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private int curCnt = 1 ;private int maxCnt = 1 ;private TreeNode preNode = null ;public int [] findMode(TreeNode root) { List<Integer> maxCntNums = new ArrayList<>(); inOrder(root, maxCntNums); int [] ret = new int [maxCntNums.size()]; int idx = 0 ; for (int num : maxCntNums) { ret[idx++] = num; } return ret; } private void inOrder (TreeNode node, List<Integer> nums) { if (node == null ) return ; inOrder(node.left, nums); if (preNode != null ) { if (preNode.val == node.val) curCnt++; else curCnt = 1 ; } if (curCnt > maxCnt) { maxCnt = curCnt; nums.clear(); nums.add(node.val); } else if (curCnt == maxCnt) { nums.add(node.val); } preNode = node; inOrder(node.right, nums); }