LeetCode 654. 最大二叉树
题目链接:654. 最大二叉树
思路:题目描述有些简略,可以看一下第一个示例,会更好理解一些。
最大二叉树的构建过程是这样的:
- 找到数组中最大的值,将这个值作为根节点;
- 以此节点将数组切分为左、右子树;
- 分别找出左(数组)、右(数组)中的最大值,将它们作为左、右子树的根节点;
- 依次类推…
Python版本:
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if not nums:
return None
maxValue = max(nums)
maxIndex = nums.index(maxValue)
root = TreeNode(maxValue)
left = nums[:maxIndex]
right = nums[maxIndex + 1:]
root.left = self.constructMaximumBinaryTree(left)
root.right = self.constructMaximumBinaryTree(right)
return root
时间复杂度: O ( n 2 ) O(n^2) O(n2),空间复杂度: O ( n ) O(n) O(n)
go版本:
func constructMaximumBinaryTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
index := max(nums)
root := &TreeNode {
Val: nums[index],
Left:constructMaximumBinaryTree(nums[:index]),
Right:constructMaximumBinaryTree(nums[index+1:])}
return root
}
func max(nums []int) (index int) {
for i:=0; i<len(nums); i++ {
if nums[i] > nums[index] {
index = i
}
}
return
}
LeetCode 617. 合并二叉树
题目链接:617. 合并二叉树
思路:这道题还是很好理解的,一眼递归。但这个题需要我们同时递归两棵树,把一个树的节点加到另一个树上,最后返回接收累加的这棵树,如果当前节点为空就直接返回另一个节点。
Python版本:
class Solution:
def mergeTrees(self, root1, root2):
if not root1:
return root2
if not root2:
return root1
root1.val += root2.val
root1.left = self.mergeTrees(root1.left, root2.left)
root1.right = self.mergeTrees(root1.right, root2.right)
return root1
时间复杂度: O ( m i n ( m , n ) ) O(min(m, n)) O(min(m,n)),空间复杂度: O ( m i n ( m , n ) ) O(min(m, n)) O(min(m,n))
go版本:
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
if root1 == nil {
return root2
}
if root2 == nil {
return root1
}
root1.Val += root2.Val
root1.Left = mergeTrees(root1.Left, root2.Left)
root1.Right = mergeTrees(root1.Right, root2.Right)
return root1
}
LeetCode 700. 二叉搜索树中的搜索
题目链接:700. 二叉搜索树中的搜索
思路:先明确一下定义,二叉搜索树定义如下:
- 若左子树不空,则左子树上所有结点的值均小于根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于根结点的值;
- 二叉搜索树的左、右子树也分别为二叉搜索树。
跟二分搜索法的递归实现很像对吧,同样此题也使用递归。单层递归逻辑还有个需要注意的点,我们需要设置一个变量来接收根节点。
Python版本:
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root:
return
if val == root.val:
return root
elif val > root.val: # 查右子树
res = self.searchBST(root.right, val)
else: # val < root.val 查左子树
res = self.searchBST(root.left, val)
return res
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( n ) O(n) O(n)
go版本:
func searchBST(root *TreeNode, val int) *TreeNode {
var res *TreeNode
if root == nil {
return res
} else if root.Val == val {
return root
} else if root.Val < val {
res = searchBST(root.Right, val)
} else {
res = searchBST(root.Left, val)
}
return res
}
go的布尔型无法参与数值运算,也无法与其他类型进行转换,不知道是优点还是缺点,但代码比python是实实在在多敲了好几个字母~
LeetCode 98. 验证二叉搜索树
题目链接:98. 验证二叉搜索树
思路:此题有一个陷阱,就是在单层递归的时候不能只比较左孩子小于根节点小于右孩子,因为可能会出现下图这种情况:
如果按照上述逻辑进行比较,代码最后输出的结果是true,但其实这不是一个二叉搜索树。所以我们需要维护一个变量来保存上一个根节点。
根据这个变量,又引申出来一个问题,就是二叉树的遍历顺序也有了讲究。如果我们用前序遍历和后序遍历会发现,一会要大于,一会又要小于,所以此题只能用中序遍历来做,因为只有中序遍历,所有数值都是单调递增的。
Python版本:
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
prev = float('-inf')
def foo(node):
if not node:
return True
nonlocal prev
left_ = foo(node.left)
if node.val <= prev:
return False
prev = node.val
right_ = foo(node.right)
return left_ and right_
return foo(root)
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( n ) O(n) O(n)
go版本:
func isValidBST(root *TreeNode) bool {
var prev *TreeNode
var foo func(node *TreeNode) bool
foo = func(node *TreeNode) bool {
if node == nil {
return true
}
left := foo(node.Left)
// 这个地方还需要判断prev是否为空
if prev != nil && node.Val <= prev.Val {
return false
}
prev = node
right := foo(node.Right)
return left && right
}
return foo(root)
}