算法-二叉树

8.完全二叉树的节点个数

class TreeNode:
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right = None
import collections
#普通二叉树递归法
class Solution:
    def countNodes(self,root:TreeNode):
        if not root:
            return 0
        return 1 + self.countNodes(root.left) + self.countNodes(root.right)
#普通二叉树迭代法:
class Solution:
    def countNodes(self,root:TreeNode):
        queue =collections.deque()
        if root:
            queue.append(root)
        res = 0
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                res += 1
                if node.left:queue.append(node.left)
                if node.right:queue.append(node.right)
        return res
#满二叉树:
class Solution:
    def countNodes(self,root:TreeNode):
        if not root:
            return 0
        left = root.left
        right = root.right
        leftH = 0
        rightH = 0
        while left:
            left = left.left
            leftH += 1
        while right:
            right = right.right
            rightH += 1
        if leftH == rightH:
            return (2 << leftH) - 1
        return self.countNodes(root.left) + self.countNodes(root.right) + 1

9.平衡二叉树

class Solution:
    def isBalanced(self,root:TreeNode):
        return self.recur(root) != -1
    def recur(self,root):
        if not root:return 0
        left = self.recur(root.left)
        if left == -1:return -1
        right = self.recur(root.right)
        if right == -1:return -1
        return max(left + right) + 1 if abs(left - right) < 2 else -1

10.二叉树的所有路径

import collections
#深度优先搜索
class Solution:
    def binaryTreePaths(self, root: TreeNode):
        def construct_paths(root, path):
            if root:
                path += str(root.val)
                if not root.left and not root.right:
                    paths.append(path)
                else:
                    path += '->'
                    construct_paths(root.left, path)
                    construct_paths(root.right, path)

        paths = []
        construct_paths(root, '')
        return paths
#广度优先搜索
class Solution:
    def binaryTreePaths(self, root: TreeNode):
        paths = list()
        if not root:
            return paths
        
        node_queue = collections.deque([root])
        path_queue = collections.deque(str(root.val))
        
        while node_queue:
            node = node_queue.popleft()
            path = path_queue.popleft()
            
            if not node.left and not node.right:
                paths.append(path)
            else:
                if node.left:
                    node_queue.append(node.left)
                    path_queue.append(path + '->' + str(node.left.val))
                if node.right:
                    node_queue.append(node.right)
                    path_queue.append(path + '->' + str(node.right.val))
        return paths

11.相同的树

class Solution:
    def isSameTree(self,p:TreeNode,q:TreeNode):
        return self.compare(p,q)
    def compare(self,tree1,tree2):
        if not tree1 and tree2:
            return False
        elif tree1 and not tree2:
            return False
        elif not tree1 and not tree2:
            return True
        elif tree1.val != tree2.val:
            return False
        
        compareLeft = self.compare(tree1.left,tree2.left)
        compareRight = self.compare(tree1.right,tree2.right)
        isSame = compareLeft and compareLeft
        return isSame

12.左叶子之和

#递归后序
class Solution:
    def sumOfLeftLeaves(self,root:TreeNode):
        if not root:
            return 0
        l_l_lea_sum = self.sumOfLeftLeaves(root.left)
        r_l_lea_sum = self.sumOfLeftLeaves(root.right)
        
        cur_left_lea_val = 0
        if root.left and not root.left.left and not root.left.right:
            cur_left_lea_val = root.left.val
        
        return cur_left_lea_val + l_l_lea_sum + r_l_lea_sum
#迭代
class Solution:
    def sumOfLeftLeaves(self, root: TreeNode):
        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

13.找树左下角的值

import collections
class Solution:
    def findBottomLeftValue(self,root:TreeNode):
        queue = collections.deque()
        if root:
            queue.append(root)
        res = 0

        while queue:
            node = queue.popleft()
            if node.right:#先右
                queue.append(node.right)
            if node.left:#后左
                queue.append(node.left)
        return node.val

14..从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树

#从前序与中序遍历序列构造二叉树
class Solution:
    def buildTree(self,preorder,inorder):
        # 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
        if not preorder:
            return None
        # 第二步: 前序遍历的第一个就是当前的中间节点.
        root_val = preorder[0]
        root = TreeNode(root_val)
        # 第三步: 找切割点.
        sepa_idx = inorder.index(root_val)
        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left = inorder[:sepa_idx]
        inorder_right = inorder[sepa_idx + 1:]
        # 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的.
        preorder_left = preorder[1:1 + len(inorder_left)]
        preorder_right = preorder[1 + len(inorder_right):]
        # 第六步: 递归
        root.left = self.buildTree(preorder_left,inorder_left)
        root.right = self.buildTree(preorder_right,inorder_right)

        return root
#从中序与后序遍历序列构造二叉树
class Solution:
    def buildTree(self,inorder,postorder):
        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None
        # 第二步: 后序遍历的最后一个就是当前的中间节点.
        root_val = postorder[-1]
        root = TreeNode(root_val)
        # 第三步: 找切割点.
        sep_idx = inorder.index(root_val)
        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left = inorder[:sep_idx]
        inorder_right = inorder[sep_idx + 1:]
        # 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
        postorder_left = postorder[: len(inorder_left)]
        postorder_right = postorder[len(inorder_left): len(inorder) - 1]
        # 第六步: 递归
        root.left = self.buildTree(inorder_left,postorder_left)
        root.right = self.buildTree(inorder_right,postorder_right)

        return root

15.最大二叉树

给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:

  • 二叉树的根是数组中的最大元素。
  • 左子树是通过数组中最大值左边部分构造出的最大二叉树。
  • 右子树是通过数组中最大值右边部分构造出的最大二叉树。

通过给定的数组构建最大二叉树,并且输出这个树的根节点。

class Solution:
    def buildTree(self,nums):
        if not nums:
            return None

        root_val = max(nums)
        root = TreeNode(root_val)

        idx = nums.index(root_val)

        nums_left = nums[:idx]
        nums_right = nums[idx + 1:]

        root.left = self.buildTree(nums_left)
        root.right = self.buildTree(nums_right)

        return root

16.合并二叉树

import collections
#递归
class Solution:
    def mergeTrees(self,root1,root2):
        # 递归终止条件:
        #  但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None.
        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
#迭代
class Solution:
    def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
        if not root1:
            return root2
        if not root2:
            return root1
        queue = collections.deque()
        queue.append(root1)
        queue.append(root2)

        while queue:
            node1 = queue.popleft()
            node2 = queue.popleft()
            # 更新queue
            # 只有两个节点都有左节点时, 再往queue里面放.
            if node1.left and node2.left:
                queue.append(node1.left)
                queue.append(node2.left)
            # 只有两个节点都有右节点时, 再往queue里面放.
            if node1.right and node2.right:
                queue.append(node1.right)
                queue.append(node2.right)
            # 更新当前节点. 同时改变当前节点的左右孩子.
            node1.val += node2.val
            if not node1.left and node2.left:
                node1.left = node2.left
            if not node1.right and node2.right:
                node1.right = node2.right
        return root1

17.路径总和①

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

#递归
class Solution:
    def haspathsum(self, root: TreeNode, targetsum: int) -> bool:
        def recur(root,tar):
            if not root.left and not root.right and tar == 0:# 遇到叶子节点,并且计数为0
                return True
            if not root.left and not root.right:# 遇到叶子节点,计数不为0
                return False
            if root.left:
                tar -= root.left.val# 左节点
                if recur(root.left,tar):return True# 递归,处理左节点
                tar += root.left.val # 回溯
            if root.right:
                tar -= root.right.val  # 右节点
                if recur(root.right, tar): return True  # 递归,处理右节点
                tar += root.right.val  # 回溯
            return False
        if not root:
            return False
        else:
            return recur(root,targetsum - root.val)
#迭代 - 层序遍历
class solution:
    def haspathsum(self, root: TreeNode, targetsum: int) -> bool:
        if not root:
            return False

        stack = []  # [(当前节点,路径数值), ...]
        stack.append((root, root.val))

        while stack:
            cur_node, path_sum = stack.pop()

            if not cur_node.left and not cur_node.right and path_sum == targetsum:
                return True

            if cur_node.right:
                stack.append((cur_node.right, path_sum + cur_node.right.val))

            if cur_node.left:
                stack.append((cur_node.left, path_sum + cur_node.left.val))

        return False

18.路径总和②

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

class solution:
    def pathsum(self, root: TreeNode, targetsum: int):
        def recur(root,tar):
            if not root.left and not root.right and tar == 0:
                res.append(path[:])
                return

            if not root.left and not root.right:return

            if root.left:
                path.append(root.left.val)
                tar -= root.left.val
                recur(root.left,tar)
                path.pop()
                tar += root.left.val

            if root.right:
                path.append(root.right.val)
                tar -= root.right.val
                recur(root.right, tar)
                path.pop()
                tar += root.right.val

        res = []
        path = []
        if not root:
            return []
        path.append(root.val)
        recur(root,targetsum - root.val)
        return res

19.二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

#递归法
class Solution:
    def searchBST(self, root: TreeNode, val: int):
        if not root:
            return None
        if root.val == val:
            return root
        if root.val > val:
            return self.searchBST(root.left,val)
        if root.val < val:
            return self.searchBST(root.right, val)
#迭代法
class Solution:
    def searchBST(self, root: TreeNode, val: int):
        while root:
            if val == root.val:
                return root
            root = root.left if val < root.val else root.right
        return None

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值