代码随想录系列
代码随想录 Day1 | Leetcode704 二分查找、Leetcode27 移除元素_(i+j)/2越界-CSDN博客https://blog.csdn.net/qq_41502639/article/details/135234321?spm=1001.2014.3001.5502代码随想录 Day2 | Leetcode997 有序数组的平方、Leetcode209 长的最小的子数组、Leetcode59 螺旋矩阵2-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135259254?spm=1001.2014.3001.5502代码随想录 Day3 | Leetcode203 移除链表元素、Leetcode707 设计链表、Leetcode206反转链表-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135331420?spm=1001.2014.3001.5502代码随想录 Day4 | Leetcode24 两两交换链表中的节点、Leetcode19 删除链表的倒数第N个节点、面试题 02.07 链表相交、Leetcode142 环形链表II-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135376417?spm=1001.2014.3001.5502代码随想录 Day5 | Leetcode242 有效的字母异位词 、Leetcode349 两个数组的交集、Leetcode202 快乐数、Leetcode1 两数之和-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135420816?spm=1001.2014.3001.5502代码随想录 Day6 | Leetcode454 四数相加、Leetcode383 赎金信、Leetcode15 三数之和、Leetcode18 四数之和-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135447496?spm=1001.2014.3001.5502代码随想录 Day7 | Leetcode344 反转字符串、Leetcode541 反转字符串2、卡码网54 替换数字、Leetcode151 翻转字符串里的单词、卡码网55 左右旋转字符串_python给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135469022?spm=1001.2014.3001.5502代码随想录 Day8 | Leetcode22 用栈实现队列、Leetcode225 用队列实现栈-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135492707?spm=1001.2014.3001.5502代码随想录 Day9 | Leetcode20 有效的括号、Leetcode541 删除字符串中的所有相邻重复项 | Leetcode150 逆波兰表达式求值-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135515537?spm=1001.2014.3001.5502代码随想录 Day10 | Leetcode239 滑动窗口最大值、Leetcode 347 前 K 个高频元素-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135542134?spm=1001.2014.3001.5502代码随想录 Day11 | Leetcode144 二叉树的前序遍历、Leetcode145 二叉树的后序遍历、Leetcode94 二叉树的中序遍历-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135614330?spm=1001.2014.3001.5502代码随想录Day12 二叉树层序遍历| Leetcode十题-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135638685?spm=1001.2014.3001.5502代码随想录 Day13 | Leetcode111 二叉树的最小深度、Leetcode222 完全二叉树的节点个数、Leetcode104 二叉树的最大深度、Leetcode559 N叉树的最大深度-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135738461?spm=1001.2014.3001.5502代码随想录 Day14 | Leetcode110 平衡二叉树、Leetcode257 二叉树的所有路径、Leetcode404 左叶子之和-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135803577?spm=1001.2014.3001.5502代码随想录 Day15 | Leetcode105、Leetcode106、Leetcode112、Leetcode113、Leetcode513-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135856991?spm=1001.2014.3001.5502代码随想录 Day16 | Leetcode654 最大二叉树、Leetcode617 合并二叉树、Leetcode700 二叉搜索树中的搜索、Leetcode98 验证二叉搜索树-CSDN博客
https://blog.csdn.net/qq_41502639/article/details/135944102?spm=1001.2014.3001.5502
上题
530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
236. 二叉树的最近公共祖先 - 力扣(LeetCode)
第一题
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3]
输出:1
示例 2:
输入:root = [1,0,48,null,null,12,49]
输出:1
思路
搜索树左子树<结点<右子树,差值最小一定会是相邻两个结点之间出现,使用中序遍历
代码
import collections
from math import inf
class TreeNode:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
"""
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3]
输出:1
示例 2:
输入:root = [1,0,48,null,null,12,49]
输出:1
"""
def create_tree(self, root):
if not root:
return None
result = TreeNode(root[0])
queue = [result]
i, n = 1, len(root)
while i < n and queue:
node = queue.pop(0)
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.left = root_node
i += 1
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.right = root_node
i += 1
return result
def getMinimumDifference1(self, root) -> int:
if not root:
return
stack = []
result = inf
pre = None
while root or stack:
if root:
stack.append(root)
root = root.left
else:
node = stack.pop()
if pre:
result = min(abs(node.val-pre.val), result)
pre = node
root = node.right
return result
def getMinimumDifference(self, root) -> int:
if not root:
return
re = []
result = inf
self.inorder(root, re)
for i in range(1, len(re)):
result = min(abs(re[i]-re[i-1]), result)
return result
def inorder(self, root, result):
if not root:
return
self.inorder(root.left, result)
result.append(root.val)
self.inorder(root.right, result)
if __name__ == '__main__':
test = Solution()
root = [[4, 2, 6, 1, 3], [1, 0, 48, 'null', 'null', 12, 49]]
for i in root:
tree = test.create_tree(i)
print(test.getMinimumDifference(tree), test.getMinimumDifference1(tree))
第二题
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2]
输出:[2]
示例 2:
输入:root = [0]
输出:[0]
思路
同上第一题,二叉搜索树使用中序遍历得到的是递增的有序序列,众数一定会相邻,如果相邻两个数不相等,则这个数一定不是众数
代码
import collections
from math import inf
class TreeNode:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
"""
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2]
输出:[2]
示例 2:
输入:root = [0]
输出:[0]
"""
def create_tree(self, root):
if not root:
return None
result = TreeNode(root[0])
queue = [result]
i, n = 1, len(root)
while i < n and queue:
node = queue.pop(0)
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.left = root_node
i += 1
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.right = root_node
i += 1
return result
def findMode1(self, root):
"""
迭代
"""
if not root:
return
result = []
stack = []
pre = None
con, max_con = 0, 0
while root or stack:
if root:
stack.append(root)
root = root.left
else:
node = stack.pop()
# 搜索树中序遍历是一个递增有序序列,出现众数只会在相邻节点
if pre and pre.val == node.val:
con += 1
else:
con = 1
if con == max_con:
result.append(node.val)
elif con > max_con:
result = [node.val]
max_con += 1
pre = node
root = node.right
return result
def findMode(self, root):
"""
递归
"""
if not root:
return
re = []
con, max_con = 1, 1
self.inorder(root, re)
result = [re[0]]
pre = re[0]
for i in range(1, len(re)):
node = re[i]
if pre == node:
con += 1
else:
con = 1
if con == max_con:
result.append(node)
elif con > max_con:
max_con = con
result = [node]
pre = node
return result
def inorder(self, root, result):
if not root:
return
self.inorder(root.left, result)
result.append(root.val)
self.inorder(root.right, result)
if __name__ == '__main__':
test = Solution()
root = [[1, 'null', 2, 2], [0]]
for i in root:
tree = test.create_tree(i)
print(test.findMode(tree), test.findMode1(tree))
第三题
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
思路
1.root等于p或q,则root即为所求 2.递归找左右子树 3.左子树找不到时:右子树可能找不到也可能找到,不管哪种情况直接返回右子树的结果即可 4. 右子树找不到时:左子树可能找不到也可能找到,不管哪种情况直接返回左子树的结果即可 5.左右子树的查询均不为空,则当前结点即为p、q的公共祖先节点 6.前序遍历
代码
本地调试容易犯错的是把p、q当作数值传递,实际上p、q是树结点
import collections
from math import inf
class TreeNode:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
"""
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
"""
def create_tree(self, root):
if not root:
return None
result = TreeNode(root[0])
queue = [result]
i, n = 1, len(root)
while i < n and queue:
node = queue.pop(0)
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.left = root_node
i += 1
if i < n and root[i] != 'null':
root_node = TreeNode(root[i])
queue.append(root_node)
node.right = root_node
i += 1
return result
def lowestCommonAncestor(self, root, p, q):
"""
1.root等于p或q,则root即为所求
2.递归找左右子树
3.左子树找不到时:右子树可能找不到也可能找到,不管哪种情况直接返回右子树的结果即可
4. 右子树找不到时:左子树可能找不到也可能找到,不管哪种情况直接返回左子树的结果即可
5.左右子树的查询均不为空,则当前结点即为p、q的公共祖先节点
6.前序遍历
"""
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 not left:
return right
if not right:
return left
return root
def find_node_by_val(self, node, val):
if node is None:
return None
if node.val == val:
return node
return self.find_node_by_val(node.left, val) or self.find_node_by_val(node.right, val)
if __name__ == '__main__':
test = Solution()
root = [[3, 5, 1, 6, 2, 0, 8, 'null', 'null', 7, 4], [3, 5, 1, 6, 2, 0, 8, 'null', 'null', 7, 4], [1, 2]]
p = [5, 5, 1]
q = [1, 4, 2]
for i in range(len(root)):
tree = test.create_tree(root[i])
p_node = test.find_node_by_val(tree, p[i])
q_node = test.find_node_by_val(tree, q[i])
print(test.lowestCommonAncestor(tree, p_node, q_node).val)
总结
不要懈怠