算法训练Day 20

LeetCode 654. 最大二叉树

题目链接:654. 最大二叉树

思路:题目描述有些简略,可以看一下第一个示例,会更好理解一些。

最大二叉树的构建过程是这样的:

  1. 找到数组中最大的值,将这个值作为根节点;
  2. 以此节点将数组切分为左、右子树;
  3. 分别找出左(数组)、右(数组)中的最大值,将它们作为左、右子树的根节点;
  4. 依次类推…

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)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值