代码随想录算法训练营第十五天|110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和 222.完全二叉树的节点个数

110.平衡二叉树

思路:

递归三部曲:

  1. 参数和返回值:传入节点作为参数,返回树的高度
  2. 终止条件:因为要考虑只有单节点情况,所以终止条件应该是当节点为空,返回高度0
  3. 递归逻辑:计算左右子树的高度,如果高度差大于1则返回false,如果全满足小于等于1则返回True。为了提前终止递归,如果高度差大于1直接返回-1,遇到-1直接返回False

代码实现如下:

# 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 isBalanced(self, root: Optional[TreeNode]) -> bool:

        if (height := self.getheight(root)) == -1:

            return False

        else:

            return True

       

    def getheight(self, node: Optional[TreeNode]) -> int:

        if not node:

            return 0

       

        if (leftheight := self.getheight(node.left)) == -1:         # 当有一个-1的时候就直接返回,提前终止递归,这里容易漏

            return -1

        if (rightheight := self.getheight(node.right)) == -1:       # 当有一个-1的时候就直接返回,提前终止递归

            return -1

        if abs(leftheight - rightheight) > 1:

            return -1

        else:

            return max(leftheight, rightheight) + 1

规范代码:

# 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 isBalanced(self, root: TreeNode) -> bool:

        if self.get_height(root) != -1:

            return True

        else:

            return False

    def get_height(self, root: TreeNode) -> int:

        # Base Case

        if not root:

            return 0

        # 左

        if (left_height := self.get_height(root.left)) == -1:

            return -1

        # 右

        if (right_height := self.get_height(root.right)) == -1:

            return -1

        # 中

        if abs(left_height - right_height) > 1:

            return -1

        else:

            return 1 + max(left_height, right_height)

迭代法:

class Solution:

    def getDepth(self, cur):

        st = []

        if cur is not None:

            st.append(cur)

        depth = 0

        result = 0

        while st:

            node = st[-1]

            if node is not None:

                st.pop()

                st.append(node)                           # 中

                st.append(None)

                depth += 1

                if node.right:

                    st.append(node.right)                 # 右

                if node.left:

                    st.append(node.left)                   # 左

            else:               

                node = st.pop()

                st.pop()

                depth -= 1

            result = max(result, depth)

        return result

    def isBalanced(self, root):

        st = []

        if root is None:

            return True

        st.append(root)

        while st:

            node = st.pop()                                 # 中

            if abs(self.getDepth(node.left) - self.getDepth(node.right)) > 1:

                return False

            if node.right:

                st.append(node.right)                       # 右(空节点不入栈)

            if node.left:

                st.append(node.left)                         # 左(空节点不入栈)

        return True

257. 二叉树的所有路径

思路:

递归三部曲:

  1. 参数和返回值:传入节点、记录路径的数组、结果数组作为参数。返回一个字符串数组。
  2. 终止条件:传入节点是叶子节点的时候,传入节点作为路径数组最后一个元素后压入结果数组。
  3. 递归逻辑:将当前节点压入路径数组后,将复制后的副本(为了回溯,否则要pop)传给下一个节点进行递归调用。

代码实现如下:

# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:

        result = []

        self.getpath(root, [], result)

        return result

    def getpath(self, node: Optional[TreeNode], path: List, result: List[str]) -> None:

        if not node.left and not node.right:

            path.append(str(node.val))

            string = "->".join(path)

            result.append(string)

        path.append(str(node.val))

        if node.left:

            self.getpath(node.left, path[:], result)

        if node.right:

            self.getpath(node.right, path[:], result)

规范代码:

# Definition for a binary tree node.class Solution:

    def traversal(self, cur, path, result):

        path.append(cur.val)  # 中

        if not cur.left and not cur.right:  # 到达叶子节点

            sPath = '->'.join(map(str, path))

            result.append(sPath)

            return

        if cur.left:  # 左

            self.traversal(cur.left, path, result)

            path.pop()  # 回溯

        if cur.right:  # 右

            self.traversal(cur.right, path, result)

            path.pop()  # 回溯

    def binaryTreePaths(self, root):

        result = []

        path = []

        if not root:

            return result

        self.traversal(root, path, result)

        return result

迭代法:

class Solution:

    def binaryTreePaths(self, root: TreeNode) -> List[str]:

        # 题目中节点数至少为1

        stack, path_st, result = [root], [str(root.val)], []

        while stack:

            cur = stack.pop()

            path = path_st.pop()

            # 如果当前节点为叶子节点,添加路径到结果中

            if not (cur.left or cur.right):

                result.append(path)

            if cur.right:

                stack.append(cur.right)

                path_st.append(path + '->' + str(cur.right.val))

            if cur.left:

                stack.append(cur.left)

                path_st.append(path + '->' + str(cur.left.val))

        return result

404.左叶子之和

思路:

如果左孩子是叶子节点,则计入加和中,否则继续遍历寻找左叶子。

递归三部曲:

  1. 参数和返回值:参数是根节点,记录结果的数组。返回值是None。
  2. 终止条件:如果自身为空或者是叶子节点,返回。如果左孩子是叶子节点,计入加和后返回。
  3. 递归逻辑:对左右子树的左叶子进行加和。

代码实现如下:

# 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 sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:

        result = []

        self.getleftleaves(root, result)

        return sum(result)

    def getleftleaves(self, node: Optional[TreeNode], result: List) -> None:

        if not node:

            return

        if not node.left and not node.right:

            return

        if node.left and not node.left.left and not node.left.right:        # 这里需要注意,一定需要node.left存在

            result.append(node.left.val)

        else:

            self.getleftleaves(node.left, result)

       

        self.getleftleaves(node.right, result)

规范代码:

# 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 sumOfLeftLeaves(self, root):

        if root is None:

            return 0

        if root.left is None and root.right is None:

            return 0

        

        leftValue = self.sumOfLeftLeaves(root.left)  # 左

        if root.left and not root.left.left and not root.left.right:  # 左子树是左叶子的情况

            leftValue = root.left.val

            

        rightValue = self.sumOfLeftLeaves(root.right)  # 右

        sum_val = leftValue + rightValue  # 中

        return sum_val

迭代法:

# 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 sumOfLeftLeaves(self, root):

        if root is None:

            return 0

        st = [root]

        result = 0

        while st:

            node = st.pop()

            if node.left and node.left.left is None and node.left.right is None:

                result += node.left.val

            if node.right:

                st.append(node.right)

            if node.left:

                st.append(node.left)

        return result


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

思路:遍历一定能做,但是要理解满二叉树的节点算法:2^n - 1,利用这个特性,完全二叉树又一定可以由若干个满二叉树来组成,所以可以使用递归。

递归三部曲:

  1. 参数和返回值:参数是传入节点。返回值是int类型节点个数。
  2. 终止条件:当节点为空,分别返回0。
  3. 递归逻辑,寻找满二叉树同时记录深度n,利用2^n-1计算节点个数,返回节点个数。

代码实现如下:

# 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 countNodes(self, root: Optional[TreeNode]) -> int:

        if not root:

            return 0

       

        n = 1

        left, right = root.left, root.right

        while left and right:

            n += 1

            left = left.left

            right = right.right

        if left and right:

            return 2 ** n - 1

        return self.countNodes(root.left) + self.countNodes(root.right) + 1

           

规范代码,递归:

class Solution:

    def countNodes(self, root: TreeNode) -> int:

        return self.getNodesNum(root)

        

    def getNodesNum(self, cur):

        if not cur:

            return 0

        leftNum = self.getNodesNum(cur.left) #左

        rightNum = self.getNodesNum(cur.right) #右

        treeNum = leftNum + rightNum + 1 #中

        return treeNum

迭代法:

import collections

class Solution:

    def countNodes(self, root: TreeNode) -> int:

        queue = collections.deque()

        if root:

            queue.append(root)

        result = 0

        while queue:

            size = len(queue)

            for i in range(size):

                node = queue.popleft()

                result += 1 #记录节点数量

                if node.left:

                    queue.append(node.left)

                if node.right:

                    queue.append(node.right)

        return result

完全二叉树:

class Solution:

    def countNodes(self, root: TreeNode) -> int:

        if not root:

            return 0

        left = root.left

        right = root.right

        leftDepth = 0 #这里初始为0是有目的的,为了下面求指数方便

        rightDepth = 0

        while left: #求左子树深度

            left = left.left

            leftDepth += 1

        while right: #求右子树深度

            right = right.right

            rightDepth += 1

        if leftDepth == rightDepth:

            return (2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0

        return self.countNodes(root.left) + self.countNodes(root.right) + 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值