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/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 c0561e10..e10a612a 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -536,18 +536,16 @@ 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 ``` 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/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/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index 66d5b3cf..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 ``` 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/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/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index 18d8a0cc..95372d61 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -271,64 +271,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 trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode: - ''' - 确认递归函数参数以及返回值:返回更新后剪枝后的当前root节点 - ''' - # Base Case - if not root: return None - - # 单层递归逻辑 + if root is None: + return None if root.val < low: - # 若当前root节点小于左界:只考虑其右子树,用于替代更新后的其本身,抛弃其左子树整体 + # 寻找符合区间 [low, high] 的节点 return self.trimBST(root.right, low, high) - - if high < root.val: - # 若当前root节点大于右界:只考虑其左子树,用于替代更新后的其本身,抛弃其右子树整体 + 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 - if low <= root.val <= high: - root.left = self.trimBST(root.left, low, high) - root.right = self.trimBST(root.right, low, high) - # 返回更新后的剪枝过的当前节点root - return root ``` - -**迭代** - +递归法(版本二)精简 ```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: + 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/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 + ``` -----