diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index 1af8787b..ca62e3ed 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -41,7 +41,7 @@ 那么我们就应该想到使用哈希法了。 -因为本地,我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,**需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适**。 +因为本地,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,**需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适**。 再来看一下使用数组和set来做哈希法的局限。 diff --git a/problems/0035.搜索插入位置.md b/problems/0035.搜索插入位置.md index efc87577..04dd0cac 100644 --- a/problems/0035.搜索插入位置.md +++ b/problems/0035.搜索插入位置.md @@ -191,8 +191,8 @@ public: }; ``` -* 时间复杂度:$O(\log n)$ -* 时间复杂度:$O(1)$ +* 时间复杂度:O(log n) +* 空间复杂度:O(1) ## 总结 diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index ccb63305..95b657a5 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -371,117 +371,113 @@ class Solution { ## Python -**递归** - 利用BST中序遍历特性,把树"压缩"成数组 +递归法(版本一)利用中序递增性质,转换成数组 ```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - def isValidBST(self, root: TreeNode) -> bool: - # 思路: 利用BST中序遍历的特性. - # 中序遍历输出的二叉搜索树节点的数值是有序序列 - candidate_list = [] - - def __traverse(root: TreeNode) -> None: - nonlocal candidate_list - if not root: - return - __traverse(root.left) - candidate_list.append(root.val) - __traverse(root.right) - - def __is_sorted(nums: list) -> bool: - for i in range(1, len(nums)): - if nums[i] <= nums[i - 1]: # ⚠️ 注意: Leetcode定义二叉搜索树中不能有重复元素 - return False - return True - - __traverse(root) - res = __is_sorted(candidate_list) - - return res -``` + def __init__(self): + self.vec = [] -**递归** - 标准做法 + def traversal(self, root): + if root is None: + return + self.traversal(root.left) + self.vec.append(root.val) # 将二叉搜索树转换为有序数组 + self.traversal(root.right) -```python -class Solution: - def isValidBST(self, root: TreeNode) -> bool: - # 规律: BST的中序遍历节点数值是从小到大. - cur_max = -float("INF") - def __isValidBST(root: TreeNode) -> bool: - nonlocal cur_max - - if not root: - return True - - is_left_valid = __isValidBST(root.left) - if cur_max < root.val: - cur_max = root.val - else: + def isValidBST(self, root): + self.vec = [] # 清空数组 + self.traversal(root) + for i in range(1, len(self.vec)): + # 注意要小于等于,搜索树里不能有相同元素 + if self.vec[i] <= self.vec[i - 1]: return False - is_right_valid = __isValidBST(root.right) - - return is_left_valid and is_right_valid - return __isValidBST(root) + return True + ``` -**递归** - 避免初始化最小值做法: + +递归法(版本二)设定极小值,进行比较 + ```python class Solution: - def isValidBST(self, root: TreeNode) -> bool: - # 规律: BST的中序遍历节点数值是从小到大. - pre = None - def __isValidBST(root: TreeNode) -> bool: - nonlocal pre - - if not root: - return True - - is_left_valid = __isValidBST(root.left) - if pre and pre.val>=root.val: return False - pre = root - is_right_valid = __isValidBST(root.right) - - return is_left_valid and is_right_valid - return __isValidBST(root) + def __init__(self): + self.maxVal = float('-inf') # 因为后台测试数据中有int最小值 + + def isValidBST(self, root): + if root is None: + return True + + left = self.isValidBST(root.left) + # 中序遍历,验证遍历的元素是不是从小到大 + if self.maxVal < root.val: + self.maxVal = root.val + else: + return False + right = self.isValidBST(root.right) + + return left and right + ``` +递归法(版本三)直接取该树的最小值 ```python -迭代-中序遍历 +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - def isValidBST(self, root: TreeNode) -> bool: + def __init__(self): + self.pre = None # 用来记录前一个节点 + + def isValidBST(self, root): + if root is None: + return True + + left = self.isValidBST(root.left) + + if self.pre is not None and self.pre.val >= root.val: + return False + self.pre = root # 记录前一个节点 + + right = self.isValidBST(root.right) + return left and right + + + +``` +迭代法 +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def isValidBST(self, root): stack = [] cur = root - pre = None - while cur or stack: - if cur: # 指针来访问节点,访问到最底层 + pre = None # 记录前一个节点 + while cur is not None or len(stack) > 0: + if cur is not None: stack.append(cur) - cur = cur.left - else: # 逐一处理节点 - cur = stack.pop() - if pre and cur.val <= pre.val: # 比较当前节点和前节点的值的大小 + cur = cur.left # 左 + else: + cur = stack.pop() # 中 + if pre is not None and cur.val <= pre.val: return False - pre = cur - cur = cur.right + pre = cur # 保存前一个访问的结点 + cur = cur.right # 右 return True ``` -```python -# 遵循Carl的写法,只添加了节点判断的部分 -class Solution: - def isValidBST(self, root: TreeNode) -> bool: - # method 2 - que, pre = [], None - while root or que: - while root: - que.append(root) - root = root.left - root = que.pop() - # 对第一个节点只做记录,对后面的节点进行比较 - if pre is None: - pre = root.val - else: - if pre >= root.val: return False - pre = root.val - root = root.right - return True -``` + ## Go diff --git a/problems/0106.从中序与后序遍历序列构造二叉树.md b/problems/0106.从中序与后序遍历序列构造二叉树.md index 8fc973e0..a0bab999 100644 --- a/problems/0106.从中序与后序遍历序列构造二叉树.md +++ b/problems/0106.从中序与后序遍历序列构造二叉树.md @@ -400,8 +400,6 @@ public: }; ``` -## Python - # 105.从前序与中序遍历序列构造二叉树 @@ -692,38 +690,6 @@ class Solution { ## Python -```python -class Solution: - def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]: - # 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件 - if not postorder: - return - - # 第二步: 后序遍历的最后一个就是当前的中间节点 - root_val = postorder[-1] - root = TreeNode(root_val) - - # 第三步: 找切割点. - root_index = inorder.index(root_val) - - # 第四步: 切割inorder数组. 得到inorder数组的左,右半边. - left_inorder = inorder[:root_index] - right_inorder = inorder[root_index + 1:] - - # 第五步: 切割postorder数组. 得到postorder数组的左,右半边. - # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的. - left_postorder = postorder[:len(left_inorder)] - right_postorder = postorder[len(left_inorder): len(postorder) - 1] - - - # 第六步: 递归 - root.left = self.buildTree(left_inorder, left_postorder) - root.right = self.buildTree(right_inorder, right_postorder) - - # 第七步: 返回答案 - return root -``` - 105.从前序与中序遍历序列构造二叉树 ```python @@ -752,7 +718,7 @@ class Solution: # 第六步: 递归 root.left = self.buildTree(preorder_left, inorder_left) root.right = self.buildTree(preorder_right, inorder_right) - + # 第七步: 返回答案 return root ``` @@ -784,7 +750,7 @@ class Solution: # 第六步: 递归 root.left = self.buildTree(inorder_left, postorder_left) root.right = self.buildTree(inorder_right, postorder_right) - + # 第七步: 返回答案 return root ``` diff --git a/problems/0108.将有序数组转换为二叉搜索树.md b/problems/0108.将有序数组转换为二叉搜索树.md index 89778421..056ef3e2 100644 --- a/problems/0108.将有序数组转换为二叉搜索树.md +++ b/problems/0108.将有序数组转换为二叉搜索树.md @@ -316,73 +316,65 @@ class Solution { ``` ## Python -**递归** - +递归法 ```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right class Solution: - def sortedArrayToBST(self, nums: List[int]) -> TreeNode: - ''' - 构造二叉树:重点是选取数组最中间元素为分割点,左侧是递归左区间;右侧是递归右区间 - 必然是平衡树 - 左闭右闭区间 - ''' - # 返回根节点 - root = self.traversal(nums, 0, len(nums)-1) - return root - def traversal(self, nums: List[int], left: int, right: int) -> TreeNode: - # Base Case if left > right: return None - # 确定左右界的中心,防越界 mid = left + (right - left) // 2 - # 构建根节点 - mid_root = TreeNode(nums[mid]) - # 构建以左右界的中心为分割点的左右子树 - mid_root.left = self.traversal(nums, left, mid-1) - mid_root.right = self.traversal(nums, mid+1, right) + root = TreeNode(nums[mid]) + root.left = self.traversal(nums, left, mid - 1) + root.right = self.traversal(nums, mid + 1, right) + return root + + def sortedArrayToBST(self, nums: List[int]) -> TreeNode: + root = self.traversal(nums, 0, len(nums) - 1) + return root - # 返回由被传入的左右界定义的某子树的根节点 - return mid_root ``` -**迭代**(左闭右开) +迭代法 ```python +from collections import deque + class Solution: - def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: - if len(nums) == 0: return None - root = TreeNode() # 初始化 - nodeSt = [root] - leftSt = [0] - rightSt = [len(nums)] - - while nodeSt: - node = nodeSt.pop() # 处理根节点 - left = leftSt.pop() - right = rightSt.pop() - mid = left + (right - left) // 2 - node.val = nums[mid] - - if left < mid: # 处理左区间 - node.left = TreeNode() - nodeSt.append(node.left) - leftSt.append(left) - rightSt.append(mid) - - if right > mid + 1: # 处理右区间 - node.right = TreeNode() - nodeSt.append(node.right) - leftSt.append(mid + 1) - rightSt.append(right) + def sortedArrayToBST(self, nums: List[int]) -> TreeNode: + if len(nums) == 0: + return None + root = TreeNode(0) # 初始根节点 + nodeQue = deque() # 放遍历的节点 + leftQue = deque() # 保存左区间下标 + rightQue = deque() # 保存右区间下标 + + nodeQue.append(root) # 根节点入队列 + leftQue.append(0) # 0为左区间下标初始位置 + rightQue.append(len(nums) - 1) # len(nums) - 1为右区间下标初始位置 + + while nodeQue: + curNode = nodeQue.popleft() + left = leftQue.popleft() + right = rightQue.popleft() + mid = left + (right - left) // 2 + + curNode.val = nums[mid] # 将mid对应的元素给中间节点 + + if left <= mid - 1: # 处理左区间 + curNode.left = TreeNode(0) + nodeQue.append(curNode.left) + leftQue.append(left) + rightQue.append(mid - 1) + + if right >= mid + 1: # 处理右区间 + curNode.right = TreeNode(0) + nodeQue.append(curNode.right) + leftQue.append(mid + 1) + rightQue.append(right) + return root + ``` ## Go diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md index a3bc77fb..e10a612a 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -536,23 +536,67 @@ class Solution: ```python class Solution: - def isBalanced(self, root: TreeNode) -> bool: - return self.height(root) != -1 - def height(self, node: TreeNode) -> int: - if not node: - return 0 - left = self.height(node.left) - if left == -1: - return -1 - right = self.height(node.right) - if right == -1 or abs(left - right) > 1: - return -1 - return max(left, right) + 1 + def isBalanced(self, root: Optional[TreeNode]) -> bool: + return self.get_hight(root) != -1 + def get_hight(self, node): + if not node: + return 0 + left = self.get_hight(node.left) + right = self.get_hight(node.right) + if left == -1 or right == -1 or abs(left - right) > 1: + return -1 + return max(left, right) + 1 ``` 迭代法: +```python +class Solution: + def getDepth(self, cur): + st = [] + if cur is not None: + st.append(cur) + depth = 0 + result = 0 + while st: + node = st[-1] + if node is not None: + st.pop() + st.append(node) # 中 + st.append(None) + depth += 1 + if node.right: + st.append(node.right) # 右 + if node.left: + st.append(node.left) # 左 + + else: + node = st.pop() + st.pop() + depth -= 1 + result = max(result, depth) + return result + + def isBalanced(self, root): + st = [] + if root is None: + return True + st.append(root) + while st: + node = st.pop() # 中 + if abs(self.getDepth(node.left) - self.getDepth(node.right)) > 1: + return False + if node.right: + st.append(node.right) # 右(空节点不入栈) + if node.left: + st.append(node.left) # 左(空节点不入栈) + return True + +``` + +迭代法精简版: + ```python class Solution: def isBalanced(self, root: Optional[TreeNode]) -> bool: @@ -576,8 +620,6 @@ class Solution: height_map[real_node] = 1 + max(left, right) return True ``` - - ### Go ```Go diff --git a/problems/0111.二叉树的最小深度.md b/problems/0111.二叉树的最小深度.md index d0bdf4be..a1fc8a93 100644 --- a/problems/0111.二叉树的最小深度.md +++ b/problems/0111.二叉树的最小深度.md @@ -302,36 +302,72 @@ class Solution { ## Python -递归法: +递归法(版本一) ```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right class Solution: - def minDepth(self, root: TreeNode) -> int: - if not root: + def getDepth(self, node): + if node is None: return 0 + leftDepth = self.getDepth(node.left) # 左 + rightDepth = self.getDepth(node.right) # 右 - if not root.left and not root.right: - return 1 + # 当一个左子树为空,右不为空,这时并不是最低点 + if node.left is None and node.right is not None: + return 1 + rightDepth - left_depth = float('inf') - right_depth = float('inf') + # 当一个右子树为空,左不为空,这时并不是最低点 + if node.left is not None and node.right is None: + return 1 + leftDepth - if root.left: - left_depth = self.minDepth(root.left) - if root.right: - right_depth = self.minDepth(root.right) - - return 1 + min(left_depth, right_depth) + result = 1 + min(leftDepth, rightDepth) + return result + + def minDepth(self, root): + return self.getDepth(root) ``` +递归法(版本二) -迭代法: +```python +class Solution: + def minDepth(self, root): + if root is None: + return 0 + if root.left is None and root.right is not None: + return 1 + self.minDepth(root.right) + if root.left is not None and root.right is None: + return 1 + self.minDepth(root.left) + return 1 + min(self.minDepth(root.left), self.minDepth(root.right)) + + +``` +递归法(版本三)前序 + +```python +class Solution: + def __init__(self): + self.result = float('inf') + + def getDepth(self, node, depth): + if node is None: + return + if node.left is None and node.right is None: + self.result = min(self.result, depth) + if node.left: + self.getDepth(node.left, depth + 1) + if node.right: + self.getDepth(node.right, depth + 1) + + def minDepth(self, root): + if root is None: + return 0 + self.getDepth(root, 1) + return self.result + + +``` +迭代法 ```python # Definition for a binary tree node. @@ -364,39 +400,7 @@ class Solution: return depth ``` -迭代法: -```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right - -class Solution: - def minDepth(self, root: TreeNode) -> int: - if not root: - return 0 - - queue = collections.deque([(root, 1)]) - - while queue: - node, depth = queue.popleft() - - # Check if the node is a leaf node - if not node.left and not node.right: - return depth - - # Add left and right child to the queue - if node.left: - queue.append((node.left, depth+1)) - if node.right: - queue.append((node.right, depth+1)) - - return 0 - -``` ## Go diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md index 63baa409..b3aea9ed 100644 --- a/problems/0226.翻转二叉树.md +++ b/problems/0226.翻转二叉树.md @@ -991,6 +991,53 @@ impl Solution { } ``` +### C# + +```csharp +//递归 +public class Solution { + public TreeNode InvertTree(TreeNode root) { + if (root == null) return root; + + swap(root); + InvertTree(root.left); + InvertTree(root.right); + return root; + } + + public void swap(TreeNode node) { + TreeNode temp = node.left; + node.left = node.right; + node.right = temp; + } +} +``` + +```csharp +//迭代 +public class Solution { + public TreeNode InvertTree(TreeNode root) { + if (root == null) return null; + Stack stack=new Stack(); + stack.Push(root); + while(stack.Count>0) + { + TreeNode node = stack.Pop(); + swap(node); + if(node.right!=null) stack.Push(node.right); + if(node.left!=null) stack.Push(node.left); + } + return root; + } + + public void swap(TreeNode node) { + TreeNode temp = node.left; + node.left = node.right; + node.right = temp; + } +} +``` +

diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index 8353303a..9777bb0b 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -275,34 +275,57 @@ class Solution { ## Python -递归法: +递归法(版本一) ```python class Solution: - """二叉搜索树的最近公共祖先 递归法""" + def traversal(self, cur, p, q): + if cur is None: + return cur + # 中 + if cur.val > p.val and cur.val > q.val: # 左 + left = self.traversal(cur.left, p, q) + if left is not None: + return left - 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 + if cur.val < p.val and cur.val < q.val: # 右 + right = self.traversal(cur.right, p, q) + if right is not None: + return right + + return cur + + def lowestCommonAncestor(self, root, p, q): + return self.traversal(root, p, q) ``` -迭代法: +迭代法(版本二)精简 ```python class Solution: - """二叉搜索树的最近公共祖先 迭代法""" + def lowestCommonAncestor(self, root, p, q): + if root.val > p.val and root.val > q.val: + return self.lowestCommonAncestor(root.left, p, q) + elif root.val < p.val and root.val < q.val: + return self.lowestCommonAncestor(root.right, p, q) + else: + return root - def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - while True: +``` + +迭代法 +```python +class Solution: + def lowestCommonAncestor(self, root, p, q): + while root: if root.val > p.val and root.val > q.val: root = root.left elif root.val < p.val and root.val < q.val: root = root.right else: return root -``` + return None + +``` ## Go 递归法: diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md index 33201def..0ebd5566 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -274,25 +274,44 @@ class Solution { ``` ## Python - +递归法(版本一) ```python class Solution: - """二叉树的最近公共祖先 递归法""" - - def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - if not root or root == p or root == q: + def lowestCommonAncestor(self, root, p, q): + if root == q or root == p or root is None: return root - + left = self.lowestCommonAncestor(root.left, p, q) right = self.lowestCommonAncestor(root.right, p, q) - - if left and right: - return root - if left: - return left - return right -``` + if left is not None and right is not None: + return root + + if left is None and right is not None: + return right + elif left is not None and right is None: + return left + else: + return None +``` +递归法(版本二)精简 +```python +class Solution: + def lowestCommonAncestor(self, root, p, q): + if root == q or root == p or root is None: + return root + + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if left is not None and right is not None: + return root + + if left is None: + return right + return left + +``` ## Go ```Go diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index c396f4a0..7bd56fbd 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -470,38 +470,34 @@ class Solution { ## Python: -递归法+回溯(版本一) +递归法+回溯 ```Python # Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -import copy -from typing import List, Optional - class Solution: - def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]: - if not root: - return [] + def traversal(self, cur, path, result): + path.append(cur.val) # 中 + if not cur.left and not cur.right: # 到达叶子节点 + sPath = '->'.join(map(str, path)) + result.append(sPath) + return + if cur.left: # 左 + self.traversal(cur.left, path, result) + path.pop() # 回溯 + if cur.right: # 右 + self.traversal(cur.right, path, result) + path.pop() # 回溯 + + def binaryTreePaths(self, root): result = [] - self.generate_paths(root, [], result) + path = [] + if not root: + return result + self.traversal(root, path, result) return result - - def generate_paths(self, node: TreeNode, path: List[int], result: List[str]) -> None: - path.append(node.val) - if not node.left and not node.right: - result.append('->'.join(map(str, path))) - if node.left: - self.generate_paths(node.left, copy.copy(path), result) - if node.right: - self.generate_paths(node.right, copy.copy(path), result) - path.pop() ``` -递归法+回溯(版本二) +递归法+隐形回溯(版本一) ```Python # Definition for a binary tree node. # class TreeNode: @@ -509,7 +505,6 @@ class Solution: # self.val = val # self.left = left # self.right = right -import copy from typing import List, Optional class Solution: @@ -517,23 +512,23 @@ class Solution: if not root: return [] result = [] - self.generate_paths(root, [], result) + self.traversal(root, [], result) return result - def generate_paths(self, node: TreeNode, path: List[int], result: List[str]) -> None: - if not node: + def traversal(self, cur: TreeNode, path: List[int], result: List[str]) -> None: + if not cur: return - path.append(node.val) - if not node.left and not node.right: + path.append(cur.val) + if not cur.left and not cur.right: result.append('->'.join(map(str, path))) - else: - self.generate_paths(node.left, copy.copy(path), result) - self.generate_paths(node.right, copy.copy(path), result) - path.pop() + if cur.left: + self.traversal(cur.left, path[:], result) + if cur.right: + self.traversal(cur.right, path[:], result) ``` -递归法+隐形回溯 +递归法+隐形回溯(版本二) ```Python # Definition for a binary tree node. # class TreeNode: @@ -566,16 +561,11 @@ class Solution: 迭代法: ```Python -from collections import deque - - class Solution: - """二叉树的所有路径 迭代法""" def binaryTreePaths(self, root: TreeNode) -> List[str]: # 题目中节点数至少为1 - stack, path_st, result = deque([root]), deque(), [] - path_st.append(str(root.val)) + stack, path_st, result = [root], [str(root.val)], [] while stack: cur = stack.pop() diff --git a/problems/0300.最长上升子序列.md b/problems/0300.最长上升子序列.md index e8cb0b5f..01d34949 100644 --- a/problems/0300.最长上升子序列.md +++ b/problems/0300.最长上升子序列.md @@ -149,7 +149,7 @@ class Solution: if len(nums) <= 1: return len(nums) dp = [1] * len(nums) - result = 0 + result = 1 for i in range(1, len(nums)): for j in range(0, i): if nums[i] > nums[j]: diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index 617978b7..aa2868df 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -247,8 +247,7 @@ class Solution { ### Python - -**递归后序遍历** +递归 ```python # Definition for a binary tree node. # class TreeNode: @@ -257,47 +256,64 @@ class Solution { # self.left = left # self.right = right class Solution: - def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int: - if not root: + def sumOfLeftLeaves(self, root): + if root is None: + return 0 + if root.left is None and root.right is None: return 0 - # 检查根节点的左子节点是否为叶节点 - if root.left and not root.left.left and not root.left.right: - left_val = root.left.val - else: - left_val = self.sumOfLeftLeaves(root.left) + leftValue = self.sumOfLeftLeaves(root.left) # 左 + if root.left and not root.left.left and not root.left.right: # 左子树是左叶子的情况 + leftValue = root.left.val - # 递归地计算右子树左叶节点的和 - right_val = self.sumOfLeftLeaves(root.right) - - return left_val + right_val + rightValue = self.sumOfLeftLeaves(root.right) # 右 + + sum_val = leftValue + rightValue # 中 + return sum_val +``` +递归精简版 + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def sumOfLeftLeaves(self, root): + if root is None: + return 0 + leftValue = 0 + if root.left is not None and root.left.left is None and root.left.right is None: + leftValue = root.left.val + return leftValue + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right) ``` -**迭代** +迭代法 ```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - def sumOfLeftLeaves(self, root: TreeNode) -> int: - """ - Idea: Each time check current node's left node. - If current node don't have one, skip it. - """ - stack = [] - if root: - stack.append(root) - res = 0 - - while stack: - # 每次都把当前节点的左节点加进去. - cur_node = stack.pop() - if cur_node.left and not cur_node.left.left and not cur_node.left.right: - res += cur_node.left.val - - if cur_node.left: - stack.append(cur_node.left) - if cur_node.right: - stack.append(cur_node.right) - - return res + def sumOfLeftLeaves(self, root): + if root is None: + return 0 + st = [root] + result = 0 + while st: + node = st.pop() + if node.left and node.left.left is None and node.left.right is None: + result += node.left.val + if node.right: + st.append(node.right) + if node.left: + st.append(node.left) + return result + ``` ### Go diff --git a/problems/0406.根据身高重建队列.md b/problems/0406.根据身高重建队列.md index 3f82d0bc..7379c126 100644 --- a/problems/0406.根据身高重建队列.md +++ b/problems/0406.根据身高重建队列.md @@ -295,19 +295,19 @@ var reconstructQueue = function(people) { ```Rust impl Solution { - pub fn reconstruct_queue(people: Vec>) -> Vec> { - let mut people = people; + pub fn reconstruct_queue(mut people: Vec>) -> Vec> { + let mut queue = vec![]; people.sort_by(|a, b| { - if a[0] == b[0] { return a[1].cmp(&b[1]); } + if a[0] == b[0] { + return a[1].cmp(&b[1]); + } b[0].cmp(&a[0]) }); - let mut que: Vec> = Vec::new(); - que.push(people[0].clone()); - for i in 1..people.len() { - let position = people[i][1]; - que.insert(position as usize, people[i].clone()); + queue.push(people[0].clone()); + for v in people.iter().skip(1) { + queue.insert(v[1] as usize, v.clone()); } - que + queue } } ``` diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index 2602b528..3d73598d 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -324,88 +324,90 @@ class Solution { ``` ## Python - +递归法(版本一) ```python class Solution: - def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: - if not root : return None # 节点为空,返回 - if root.val < key : - root.right = self.deleteNode(root.right, key) - elif root.val > key : + def deleteNode(self, root, key): + 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) - else: - # 当前节点的左子树为空,返回当前的右子树 - if not root.left : return root.right - # 当前节点的右子树为空,返回当前的左子树 - if not root.right: return root.left - # 左右子树都不为空,找到右孩子的最左节点 记为p - node = root.right - while node.left : - node = node.left - # 将当前节点的左子树挂在p的左孩子上 - node.left = root.left - # 当前节点的右子树替换掉当前节点,完成当前节点的删除 - root = root.right + if root.val < key: + root.right = self.deleteNode(root.right, key) return root ``` -**普通二叉树的删除方式** +递归法(版本二) ```python class Solution: - def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: - if not root: return root - if root.val == key: - if not root.right: # 这里第二次操作目标值:最终删除的作用 + def deleteNode(self, root, key): + if root is None: # 如果根节点为空,直接返回 + return root + if root.val == key: # 找到要删除的节点 + if root.right is None: # 如果右子树为空,直接返回左子树作为新的根节点 return root.left - tmp = root.right - while tmp.left: - tmp = tmp.left - root.val, tmp.val = tmp.val, root.val # 这里第一次操作目标值:交换目标值其右子树最左面节点。 - - root.left = self.deleteNode(root.left, key) - root.right = self.deleteNode(root.right, key) + cur = root.right + while cur.left: # 找到右子树中的最左节点 + cur = cur.left + root.val, cur.val = cur.val, root.val # 将要删除的节点值与最左节点值交换 + root.left = self.deleteNode(root.left, key) # 在左子树中递归删除目标节点 + root.right = self.deleteNode(root.right, key) # 在右子树中递归删除目标节点 return root + ``` **迭代法** ```python class Solution: - def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: - # 找到节点后分两步,1. 把节点的左子树和右子树连起来,2. 把右子树跟父节点连起来 - # root is None - if not root: return root - p = root - last = None - while p: - if p.val==key: - # 1. connect left to right - # right is not None -> left is None | left is not None - if p.right: - if p.left: - node = p.right - while node.left: - node = node.left - node.left = p.left - right = p.right - else: - # right is None -> right=left - right = p.left - # 2. connect right to last - if last==None: - root = right - elif last.val>key: - last.left = right - else: - last.right = right - # 3. return + def deleteOneNode(self, target: TreeNode) -> TreeNode: + """ + 将目标节点(删除节点)的左子树放到目标节点的右子树的最左面节点的左孩子位置上 + 并返回目标节点右孩子为新的根节点 + 是动画里模拟的过程 + """ + if target is None: + return target + if target.right is None: + return target.left + cur = target.right + while cur.left: + cur = cur.left + cur.left = target.left + return target.right + + def deleteNode(self, root: TreeNode, key: int) -> TreeNode: + if root is None: + return root + cur = root + pre = None # 记录cur的父节点,用来删除cur + while cur: + if cur.val == key: break + pre = cur + if cur.val > key: + cur = cur.left else: - # Update last and continue - last = p - if p.val>key: - p = p.left - else: - p = p.right + cur = cur.right + if pre is None: # 如果搜索树只有头结点 + return self.deleteOneNode(cur) + # pre 要知道是删左孩子还是右孩子 + 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) return root ``` @@ -680,6 +682,40 @@ object Solution { } ``` +## rust + +```rust +impl Solution { + pub fn delete_node( + root: Option>>, + key: i32, + ) -> Option>> { + root.as_ref()?; + + let mut node = root.as_ref().unwrap().borrow_mut(); + match node.val.cmp(&key) { + std::cmp::Ordering::Less => node.right = Self::delete_node(node.right.clone(), key), + std::cmp::Ordering::Equal => match (node.left.clone(), node.right.clone()) { + (None, None) => return None, + (None, Some(r)) => return Some(r), + (Some(l), None) => return Some(l), + (Some(l), Some(r)) => { + let mut cur = Some(r.clone()); + while let Some(n) = cur.clone().unwrap().borrow().left.clone() { + cur = Some(n); + } + cur.unwrap().borrow_mut().left = Some(l); + return Some(r); + } + }, + std::cmp::Ordering::Greater => node.left = Self::delete_node(node.left.clone(), key), + } + drop(node); + root + } +} +``` +

diff --git a/problems/0501.二叉搜索树中的众数.md b/problems/0501.二叉搜索树中的众数.md index e467bf8a..1da32343 100644 --- a/problems/0501.二叉搜索树中的众数.md +++ b/problems/0501.二叉搜索树中的众数.md @@ -528,8 +528,7 @@ class Solution { ## Python -> 递归法 -> 常量空间,递归产生的栈不算 +递归法(版本一)利用字典 ```python # Definition for a binary tree node. @@ -538,77 +537,108 @@ class Solution { # self.val = val # self.left = left # self.right = right +from collections import defaultdict + class Solution: - def __init__(self): - self.pre = TreeNode() - self.count = 0 - self.max_count = 0 - self.result = [] + def searchBST(self, cur, freq_map): + if cur is None: + return + freq_map[cur.val] += 1 # 统计元素频率 + self.searchBST(cur.left, freq_map) + self.searchBST(cur.right, freq_map) - def findMode(self, root: TreeNode) -> List[int]: - if not root: return None - self.search_BST(root) - return self.result - - def search_BST(self, cur: TreeNode) -> None: - if not cur: return None - self.search_BST(cur.left) - # 第一个节点 - if not self.pre: - self.count = 1 - # 与前一个节点数值相同 - elif self.pre.val == cur.val: - self.count += 1 - # 与前一个节点数值不相同 - else: - self.count = 1 - self.pre = cur + def findMode(self, root): + freq_map = defaultdict(int) # key:元素,value:出现频率 + result = [] + if root is None: + return result + self.searchBST(root, freq_map) + max_freq = max(freq_map.values()) + for key, freq in freq_map.items(): + if freq == max_freq: + result.append(key) + return result - if self.count == self.max_count: - self.result.append(cur.val) - - if self.count > self.max_count: - self.max_count = self.count - self.result = [cur.val] # 清空self.result,确保result之前的的元素都失效 - - self.search_BST(cur.right) ``` +递归法(版本二)利用二叉搜索树性质 -> 迭代法-中序遍历 -> 利用二叉搜索树特性,在历遍过程中更新结果,一次历遍 -> 但需要使用额外空间存储历遍的节点 ```python class Solution: - def findMode(self, root: TreeNode) -> List[int]: - stack = [] + def __init__(self): + self.maxCount = 0 # 最大频率 + self.count = 0 # 统计频率 + self.pre = None + self.result = [] + + def searchBST(self, cur): + if cur is None: + return + + self.searchBST(cur.left) # 左 + # 中 + if self.pre is None: # 第一个节点 + self.count = 1 + elif self.pre.val == cur.val: # 与前一个节点数值相同 + self.count += 1 + else: # 与前一个节点数值不同 + self.count = 1 + self.pre = cur # 更新上一个节点 + + if self.count == self.maxCount: # 如果与最大值频率相同,放进result中 + self.result.append(cur.val) + + if self.count > self.maxCount: # 如果计数大于最大值频率 + self.maxCount = self.count # 更新最大频率 + self.result = [cur.val] # 很关键的一步,不要忘记清空result,之前result里的元素都失效了 + + self.searchBST(cur.right) # 右 + return + + def findMode(self, root): + self.count = 0 + self.maxCount = 0 + self.pre = None # 记录前一个节点 + self.result = [] + + self.searchBST(root) + return self.result +``` +迭代法 +```python +class Solution: + def findMode(self, root): + st = [] cur = root pre = None - maxCount, count = 0, 0 - res = [] - while cur or stack: - if cur: # 指针来访问节点,访问到最底层 - stack.append(cur) - cur = cur.left - else: # 逐一处理节点 - cur = stack.pop() - if pre == None: # 第一个节点 + maxCount = 0 # 最大频率 + count = 0 # 统计频率 + result = [] + + while cur is not None or st: + if cur is not None: # 指针来访问节点,访问到最底层 + st.append(cur) # 将访问的节点放进栈 + cur = cur.left # 左 + else: + cur = st.pop() + if pre is None: # 第一个节点 count = 1 elif pre.val == cur.val: # 与前一个节点数值相同 count += 1 - else: + else: # 与前一个节点数值不同 count = 1 - if count == maxCount: - res.append(cur.val) - if count > maxCount: - maxCount = count - res.clear() - res.append(cur.val) + + if count == maxCount: # 如果和最大值相同,放进result中 + result.append(cur.val) + + if count > maxCount: # 如果计数大于最大值频率 + maxCount = count # 更新最大频率 + result = [cur.val] # 很关键的一步,不要忘记清空result,之前result里的元素都失效了 pre = cur - cur = cur.right - return res - + cur = cur.right # 右 + + return result ``` ## Go diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md index 26768c74..743b0df9 100644 --- a/problems/0513.找树左下角的值.md +++ b/problems/0513.找树左下角的值.md @@ -330,19 +330,24 @@ class Solution: # self.right = right from collections import deque class Solution: - def findBottomLeftValue(self, root: Optional[TreeNode]) -> int: - queue = deque([root]) + def findBottomLeftValue(self, root): + if root is None: + return 0 + queue = deque() + queue.append(root) + result = 0 while queue: size = len(queue) - leftmost = queue[0].val for i in range(size): node = queue.popleft() + if i == 0: + result = node.val if node.left: queue.append(node.left) if node.right: queue.append(node.right) - if not queue: - return leftmost + return result + ``` diff --git a/problems/0530.二叉搜索树的最小绝对差.md b/problems/0530.二叉搜索树的最小绝对差.md index cd24c6fa..3e4391d6 100644 --- a/problems/0530.二叉搜索树的最小绝对差.md +++ b/problems/0530.二叉搜索树的最小绝对差.md @@ -237,66 +237,82 @@ class Solution { ``` ## Python -递归 +递归法(版本一)利用中序递增,结合数组 ```python class Solution: - def getMinimumDifference(self, root: TreeNode) -> int: - res = [] - r = float("inf") - def buildaList(root): //把二叉搜索树转换成有序数组 - if not root: return None - if root.left: buildaList(root.left) //左 - res.append(root.val) //中 - if root.right: buildaList(root.right) //右 - return res - - buildaList(root) - for i in range(len(res)-1): // 统计有序数组的最小差值 - r = min(abs(res[i]-res[i+1]),r) - return r - - -class Solution: # 双指针法,不用数组 (同Carl写法) - 更快 - def getMinimumDifference(self, root: Optional[TreeNode]) -> int: - global pre,minval - pre = None - minval = 10**5 - self.traversal(root) - return minval + def __init__(self): + self.vec = [] - def traversal(self,root): - global pre,minval - if not root: return None + def traversal(self, root): + if root is None: + return self.traversal(root.left) - if pre and root.val-pre.val int: + def __init__(self): + self.result = float('inf') + self.pre = None + + def traversal(self, cur): + if cur is None: + return + self.traversal(cur.left) # 左 + if self.pre is not None: # 中 + self.result = min(self.result, cur.val - self.pre.val) + self.pre = cur # 记录前一个 + self.traversal(cur.right) # 右 + + def getMinimumDifference(self, root): + self.traversal(root) + return self.result + + +``` + +迭代法 +```python +class Solution: + def getMinimumDifference(self, root): stack = [] cur = root pre = None result = float('inf') - while cur or stack: - if cur: # 指针来访问节点,访问到最底层 - stack.append(cur) - cur = cur.left - else: # 逐一处理节点 + + while cur is not None or len(stack) > 0: + if cur is not None: + stack.append(cur) # 将访问的节点放进栈 + cur = cur.left # 左 + else: cur = stack.pop() - if pre: # 当前节点和前节点的值的差值 - result = min(result, abs(cur.val - pre.val)) + if pre is not None: # 中 + result = min(result, cur.val - pre.val) pre = cur - cur = cur.right + cur = cur.right # 右 + return result + + ``` - ## Go: 中序遍历,然后计算最小差值 diff --git a/problems/0538.把二叉搜索树转换为累加树.md b/problems/0538.把二叉搜索树转换为累加树.md index ad5310e1..ad4decc5 100644 --- a/problems/0538.把二叉搜索树转换为累加树.md +++ b/problems/0538.把二叉搜索树转换为累加树.md @@ -200,8 +200,30 @@ class Solution { ``` ## Python -**递归** - +递归法(版本一) +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def convertBST(self, root: TreeNode) -> TreeNode: + self.pre = 0 # 记录前一个节点的数值 + self.traversal(root) + return root + def traversal(self, cur): + if cur is None: + return + self.traversal(cur.right) + cur.val += self.pre + self.pre = cur.val + self.traversal(cur.left) + + +``` +递归法(版本二) ```python # Definition for a binary tree node. # class TreeNode: @@ -234,7 +256,32 @@ class Solution: return root ``` -**迭代** +迭代法(版本一) +```python +class Solution: + def __init__(self): + self.pre = 0 # 记录前一个节点的数值 + + def traversal(self, root): + stack = [] + cur = root + while cur or stack: + if cur: + stack.append(cur) + cur = cur.right # 右 + else: + cur = stack.pop() # 中 + cur.val += self.pre + self.pre = cur.val + cur = cur.left # 左 + + def convertBST(self, root): + self.pre = 0 + self.traversal(root) + return root + +``` +迭代法(版本二) ```python class Solution: def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]: diff --git a/problems/0617.合并二叉树.md b/problems/0617.合并二叉树.md index f98948f0..18a245c4 100644 --- a/problems/0617.合并二叉树.md +++ b/problems/0617.合并二叉树.md @@ -352,8 +352,7 @@ class Solution { ``` ### Python - -**递归法 - 前序遍历** +(版本一) 递归 - 前序 - 修改root1 ```python # Definition for a binary tree node. # class TreeNode: @@ -377,8 +376,33 @@ class Solution: return root1 # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间. ``` +(版本二) 递归 - 前序 - 新建root +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode: + # 递归终止条件: + # 但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None. + if not root1: + return root2 + if not root2: + return root1 + # 上面的递归终止条件保证了代码执行到这里root1, root2都非空. + root = TreeNode() # 创建新节点 + root.val += root1.val + root2.val# 中 + root.left = self.mergeTrees(root1.left, root2.left) #左 + root.right = self.mergeTrees(root1.right, root2.right) # 右 + + return root # ⚠️ 注意: 本题我们创建了新节点. -**迭代法** +``` + +(版本三) 迭代 ```python class Solution: def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode: @@ -413,7 +437,44 @@ class Solution: return root1 ``` +(版本四) 迭代 + 代码优化 +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +from collections import deque +class Solution: + def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode: + if not root1: + return root2 + if not root2: + return root1 + + queue = deque() + queue.append((root1, root2)) + + while queue: + node1, node2 = queue.popleft() + node1.val += node2.val + + if node1.left and node2.left: + queue.append((node1.left, node2.left)) + elif not node1.left: + node1.left = node2.left + + if node1.right and node2.right: + queue.append((node1.right, node2.right)) + elif not node1.right: + node1.right = node2.right + + return root1 + + +``` ### Go ```go diff --git a/problems/0647.回文子串.md b/problems/0647.回文子串.md index 521c8c26..e172de54 100644 --- a/problems/0647.回文子串.md +++ b/problems/0647.回文子串.md @@ -238,33 +238,24 @@ Java: ```java class Solution { public int countSubstrings(String s) { - int len, ans = 0; - if (s == null || (len = s.length()) < 1) return 0; - //dp[i][j]:s字符串下标i到下标j的字串是否是一个回文串,即s[i, j] + char[] chars = s.toCharArray(); + int len = chars.length; boolean[][] dp = new boolean[len][len]; - for (int j = 0; j < len; j++) { - for (int i = 0; i <= j; i++) { - //当两端字母一样时,才可以两端收缩进一步判断 - if (s.charAt(i) == s.charAt(j)) { - //i++,j--,即两端收缩之后i,j指针指向同一个字符或者i超过j了,必然是一个回文串 - if (j - i < 3) { + int result = 0; + for (int i = len - 1; i >= 0; i--) { + for (int j = i; j < len; j++) { + if (chars[i] == chars[j]) { + if (j - i <= 1) { // 情况一 和 情况二 + result++; + dp[i][j] = true; + } else if (dp[i + 1][j - 1]) { //情况三 + result++; dp[i][j] = true; - } else { - //否则通过收缩之后的字串判断 - dp[i][j] = dp[i + 1][j - 1]; } - } else {//两端字符不一样,不是回文串 - dp[i][j] = false; } } } - //遍历每一个字串,统计回文串个数 - for (int i = 0; i < len; i++) { - for (int j = 0; j < len; j++) { - if (dp[i][j]) ans++; - } - } - return ans; + return result; } } diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md index 64b38b48..33a9176e 100644 --- a/problems/0654.最大二叉树.md +++ b/problems/0654.最大二叉树.md @@ -259,52 +259,75 @@ class Solution { ``` ### Python - +(版本一) 基础版 ```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - """递归法 更快""" def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode: - if not nums: - return None - maxvalue = max(nums) - index = nums.index(maxvalue) + if len(nums) == 1: + return TreeNode(nums[0]) + node = TreeNode(0) + # 找到数组中最大的值和对应的下标 + maxValue = 0 + maxValueIndex = 0 + for i in range(len(nums)): + if nums[i] > maxValue: + maxValue = nums[i] + maxValueIndex = i + node.val = maxValue + # 最大值所在的下标左区间 构造左子树 + if maxValueIndex > 0: + new_list = nums[:maxValueIndex] + node.left = self.constructMaximumBinaryTree(new_list) + # 最大值所在的下标右区间 构造右子树 + if maxValueIndex < len(nums) - 1: + new_list = nums[maxValueIndex+1:] + node.right = self.constructMaximumBinaryTree(new_list) + return node - root = TreeNode(maxvalue) +``` +(版本二) 使用下标 +```python - left = nums[:index] - right = nums[index + 1:] - - root.left = self.constructMaximumBinaryTree(left) - root.right = self.constructMaximumBinaryTree(right) - return root - class Solution: - """最大二叉树 递归法""" + def traversal(self, nums: List[int], left: int, right: int) -> TreeNode: + if left >= right: + return None + maxValueIndex = left + for i in range(left + 1, right): + if nums[i] > nums[maxValueIndex]: + maxValueIndex = i + root = TreeNode(nums[maxValueIndex]) + root.left = self.traversal(nums, left, maxValueIndex) + root.right = self.traversal(nums, maxValueIndex + 1, right) + return root def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode: return self.traversal(nums, 0, len(nums)) - - def traversal(self, nums: List[int], begin: int, end: int) -> TreeNode: - # 列表长度为0时返回空节点 - if begin == end: - return None - - # 找到最大的值和其对应的下标 - max_index = begin - for i in range(begin, end): - if nums[i] > nums[max_index]: - max_index = i - - # 构建当前节点 - root = TreeNode(nums[max_index]) - - # 递归构建左右子树 - root.left = self.traversal(nums, begin, max_index) - root.right = self.traversal(nums, max_index + 1, end) - - return root -``` + ``` + +(版本三) 使用切片 + +```python + +class Solution: + def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode: + if not nums: + return None + max_val = max(nums) + max_index = nums.index(max_val) + node = TreeNode(max_val) + node.left = self.constructMaximumBinaryTree(nums[:max_index]) + node.right = self.constructMaximumBinaryTree(nums[max_index+1:]) + return node + +``` ### Go diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index 18d8a0cc..85922a1d 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -248,6 +248,8 @@ public: ## Java +**递归** + ```Java class Solution { public TreeNode trimBST(TreeNode root, int low, int high) { @@ -269,66 +271,114 @@ class Solution { ``` -## Python - -**递归** - -```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -class Solution: - def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode: - ''' - 确认递归函数参数以及返回值:返回更新后剪枝后的当前root节点 - ''' - # Base Case - if not root: return None - - # 单层递归逻辑 - if root.val < low: - # 若当前root节点小于左界:只考虑其右子树,用于替代更新后的其本身,抛弃其左子树整体 - return self.trimBST(root.right, low, high) - - if high < root.val: - # 若当前root节点大于右界:只考虑其左子树,用于替代更新后的其本身,抛弃其右子树整体 - return self.trimBST(root.left, low, high) - - if low <= root.val <= high: - root.left = self.trimBST(root.left, low, high) - root.right = self.trimBST(root.right, low, high) - # 返回更新后的剪枝过的当前节点root - return root -``` - **迭代** +```Java +class Solution { + //iteration + public TreeNode trimBST(TreeNode root, int low, int high) { + if(root == null) + return null; + while(root != null && (root.val < low || root.val > high)){ + if(root.val < low) + root = root.right; + else + root = root.left; + } + + TreeNode curr = root; + + //deal with root's left sub-tree, and deal with the value smaller than low. + while(curr != null){ + while(curr.left != null && curr.left.val < low){ + curr.left = curr.left.right; + } + curr = curr.left; + } + //go back to root; + curr = root; + + //deal with root's righg sub-tree, and deal with the value bigger than high. + while(curr != null){ + while(curr.right != null && curr.right.val > high){ + curr.right = curr.right.left; + } + curr = curr.right; + } + return root; + } +} + +```` + +## Python + +递归法(版本一) ```python class Solution: - def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]: - if not root: return root - # 处理头结点,让root移动到[L, R] 范围内,注意是左闭右开 - while root and (root.val < low or root.val > high): - if root.val < low: # 小于L往右走 - root = root.right - else: # 大于R往左走 - root = root.left - # 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况 + def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode: + if root is None: + return None + if root.val < low: + # 寻找符合区间 [low, high] 的节点 + return self.trimBST(root.right, low, high) + if root.val > high: + # 寻找符合区间 [low, high] 的节点 + return self.trimBST(root.left, low, high) + root.left = self.trimBST(root.left, low, high) # root.left 接入符合条件的左孩子 + root.right = self.trimBST(root.right, low, high) # root.right 接入符合条件的右孩子 + return root + +``` +递归法(版本二)精简 +```python +class Solution: + def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode: + if root is None: + return None + if root.val < low: + return self.trimBST(root.right, low, high) + if root.val > high: + return self.trimBST(root.left, low, high) + root.left = self.trimBST(root.left, low, high) + root.right = self.trimBST(root.right, low, high) + return root + + +``` + +迭代法 +```python +class Solution: + def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode: + if not root: + return None + + # 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭 + while root and (root.val < L or root.val > R): + if root.val < L: + root = root.right # 小于L往右走 + else: + root = root.left # 大于R往左走 + cur = root + + # 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况 while cur: - while cur.left and cur.left.val < low: + while cur.left and cur.left.val < L: cur.left = cur.left.right cur = cur.left - # 此时root已经在[L, R] 范围内,处理右孩子大于R的情况 + cur = root + + # 此时root已经在[L, R] 范围内,处理右孩子大于R的情况 while cur: - while cur.right and cur.right.val > high: + while cur.right and cur.right.val > R: cur.right = cur.right.left cur = cur.right + return root + ``` ## Go diff --git a/problems/0700.二叉搜索树中的搜索.md b/problems/0700.二叉搜索树中的搜索.md index 40724f48..13064f97 100644 --- a/problems/0700.二叉搜索树中的搜索.md +++ b/problems/0700.二叉搜索树中的搜索.md @@ -230,7 +230,7 @@ class Solution { ### Python -递归法: +(方法一) 递归 ```python class Solution: @@ -250,12 +250,12 @@ class Solution: ``` -迭代法: +(方法二)迭代 ```python class Solution: def searchBST(self, root: TreeNode, val: int) -> TreeNode: - while root is not None: + while root: if val < root.val: root = root.left elif val > root.val: root = root.right else: return root diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md index 4e834201..1ba7461f 100644 --- a/problems/0701.二叉搜索树中的插入操作.md +++ b/problems/0701.二叉搜索树中的插入操作.md @@ -256,132 +256,103 @@ class Solution { ----- ## Python -**递归法** - 有返回值 - +递归法(版本一) ```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - # 返回更新后的以当前root为根节点的新树,方便用于更新上一层的父子节点关系链 + def __init__(self): + self.parent = None - # Base Case - if not root: return TreeNode(val) + def traversal(self, cur, val): + if cur is None: + node = TreeNode(val) + if val > self.parent.val: + self.parent.right = node + else: + self.parent.left = node + return - # 单层递归逻辑: - if val < root.val: - # 将val插入至当前root的左子树中合适的位置 - # 并更新当前root的左子树为包含目标val的新左子树 - root.left = self.insertIntoBST(root.left, val) + self.parent = cur + if cur.val > val: + self.traversal(cur.left, val) + if cur.val < val: + self.traversal(cur.right, val) - if root.val < val: - # 将val插入至当前root的右子树中合适的位置 - # 并更新当前root的右子树为包含目标val的新右子树 - root.right = self.insertIntoBST(root.right, val) - - # 返回更新后的以当前root为根节点的新树 + def insertIntoBST(self, root, val): + self.parent = TreeNode(0) + if root is None: + return TreeNode(val) + self.traversal(root, val) return root + ``` -**递归法** - 无返回值 +递归法(版本二) ```python class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - if not root: + def insertIntoBST(self, root, val): + if root is None: return TreeNode(val) parent = None - def __traverse(cur: TreeNode, val: int) -> None: - # 在函数运行的同时把新节点插入到该被插入的地方. - nonlocal parent - if not cur: - new_node = TreeNode(val) - if parent.val < val: - parent.right = new_node - else: - parent.left = new_node - return - - parent = cur # 重点: parent的作用只有运行到上面if not cur:才会发挥出来. - if cur.val < val: - __traverse(cur.right, val) - else: - __traverse(cur.left, val) - return - __traverse(root, val) - return root -``` - -**递归法** - 无返回值 - another easier way -```python -class Solution: - def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: - newNode = TreeNode(val) - if not root: return newNode - - if not root.left and val < root.val: - root.left = newNode - if not root.right and val > root.val: - root.right = newNode - - if val < root.val: - self.insertIntoBST(root.left, val) - if val > root.val: - self.insertIntoBST(root.right, val) - - return root -``` - -**递归法** - 无返回值 有注释 不用Helper function -```python -class Solution: - def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: - if not root: # for root==None - return TreeNode(val) - if root.valval: - if root.left==None: # found the parent - root.left = TreeNode(val) - else: # not found, keep searching - self.insertIntoBST(root.left, val) - # return the final tree - return root -``` - -**迭代法** -与无返回值的递归函数的思路大体一致 -```python -class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - if not root: - return TreeNode(val) - parent = None # 此步可以省略 cur = root - - # 用while循环不断地找新节点的parent - while cur: - parent = cur # 首先保存当前非空节点作为下一次迭代的父节点 - if cur.val < val: - cur = cur.right - elif cur.val > val: + while cur: + parent = cur + if val < cur.val: cur = cur.left - - # 运行到这意味着已经跳出上面的while循环, - # 同时意味着新节点的parent已经被找到. - # parent已被找到, 新节点已经ready. 把两个节点黏在一起就好了. - if parent.val > val: + else: + cur = cur.right + if val < parent.val: parent.left = TreeNode(val) - else: + else: parent.right = TreeNode(val) - return root +``` + +递归法(版本三) +```python +class Solution: + def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: + if root is None or root.val == val: + return TreeNode(val) + elif root.val > val: + if root.left is None: + root.left = TreeNode(val) + else: + self.insertIntoBST(root.left, val) + elif root.val < val: + if root.right is None: + root.right = TreeNode(val) + else: + self.insertIntoBST(root.right, val) + return root +``` + + + +迭代法 +```python +class Solution: + def insertIntoBST(self, root, val): + if root is None: # 如果根节点为空,创建新节点作为根节点并返回 + node = TreeNode(val) + return node + + cur = root + parent = root # 记录上一个节点,用于连接新节点 + while cur is not None: + parent = cur + if cur.val > val: + cur = cur.left + else: + cur = cur.right + + node = TreeNode(val) + if val < parent.val: + parent.left = node # 将新节点连接到父节点的左子树 + else: + parent.right = node # 将新节点连接到父节点的右子树 + + return root + ``` ----- diff --git a/problems/二叉树理论基础.md b/problems/二叉树理论基础.md index 3afedc82..dbf42ca4 100644 --- a/problems/二叉树理论基础.md +++ b/problems/二叉树理论基础.md @@ -195,15 +195,16 @@ Java: ```java public class TreeNode { int val; - TreeNode left; - TreeNode right; - TreeNode() {} - TreeNode(int val) { this.val = val; } - TreeNode(int val, TreeNode left, TreeNode right) { - this.val = val; - this.left = left; - this.right = right; - } + TreeNode left; + TreeNode right; + + TreeNode() {} + TreeNode(int val) { this.val = val; } + TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } } ``` @@ -212,10 +213,10 @@ Python: ```python class TreeNode: - def __init__(self, value): - self.value = value - self.left = None - self.right = None + def __init__(self, val, left = None, right = None): + self.val = val + self.left = left + self.right = right ``` Go: