Beispiel #1
0
# @File : 199.py
# @Description :
# @Software: PyCharm
"""二叉树的右视图
关键字: 层序遍历
思路:
1、每次只取当前层的最后一个节点
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def rightSideView(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        q = [root]
        ret = []
        while q:
            size = len(q)
            for i in range(size):
                cur = q.pop(0)
                if i + 1 == size:
                    ret.append(cur.val)
                if cur.left: q.append(cur.left)
                if cur.right: q.append(cur.right)
        return ret


print(Solution().rightSideView(createBiTree([1, 2, 3, None, 5, None, 4])))
Beispiel #2
0
# @File : 110.py
# @Description :
# @Software: PyCharm
"""平衡二叉树
关键字: 后序遍历
思路:
1、定义法: 验证左右孩子的深度差是否大于1
"""
from utils import TreeNode, createBiTree


class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        flag = True

        def dfs(root):
            if not root:
                return 0
            left = dfs(root.left)
            right = dfs(root.right)
            if abs(right - left) > 1:
                nonlocal flag
                flag = False
            return max(left, right) + 1

        dfs(root)
        return flag


print(Solution().isBalanced(createBiTree([1, 2, 3, 4, 5, None, None, 8])))
Beispiel #3
0
    def isCousins(self, root: TreeNode, x: int, y: int) -> bool:
        q = [root]
        if root.val in [x, y]:
            return False
        while q:
            size = len(q)
            count = 0
            for i in range(size):
                cnt = 0
                cur = q.pop(0)
                if cur.left:
                    if cur.left.val in [x, y]:
                        count += 1
                        cnt += 1
                    q.append(cur.left)
                if cur.right:
                    if cur.right.val in [x, y]:
                        count += 1
                        cnt += 1
                    q.append(cur.right)
                if cnt == 2:
                    return False
            if count == 1:
                return False
            if count == 2:
                return True
        return False


print(Solution().isCousins(createBiTree([1, 2, 3, None, 4, None, 5]), 5, 4))
Beispiel #4
0
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        box = []

        def dfs(root, x, y):
            if not root:
                return
            box.append((x, y, root.val))
            dfs(root.left, x - 1, y + 1)
            dfs(root.right, x + 1, y + 1)

        dfs(root, 0, 0)
        ret = []
        last_x = None
        for x, y, value in sorted(box):
            if last_x is None or last_x != x:
                ret.append([])
            ret[-1].append(value)
            last_x = x

        return ret


print(Solution().verticalTraversal(createBiTree([3, 9, 20, None, None, 15,
                                                 7])))
Beispiel #5
0
# @Description :
# @Software: PyCharm
"""二叉树的层序遍历
关键字: BFS、层次遍历
目标: 返回包含每层节点值的嵌套列表
思路: 分层处理
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        ret = []
        if not root:
            return ret
        q = [root]
        while q:
            size = len(q)
            curs = []
            for i in range(size):
                cur = q.pop(0)
                curs.append(cur.val)
                if cur.left: q.append(cur.left)
                if cur.right: q.append(cur.right)
            ret.append(curs)
        return ret


print(Solution().levelOrder(createBiTree([3, 9, 20, None, None, 15, 7])))
Beispiel #6
0
# @Time : 2020/10/10 9:28
# @Author : LiuBin
# @File : 104.py
# @Description :
# @Software: PyCharm
"""二叉树的最大深度
关键字:后序遍历、分治
目标:获得从根节点到最远的叶子结点的节点数
思路:
1、获得左子树的最大深度;获得右子树的最大深度
2、返回左/右子树的最大的深度 + 1(自己贡献了1个深度)
"""
from utils import TreeNode, createBiTree


class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        left_max_depth = self.maxDepth(root.left)
        right_max_depth = self.maxDepth(root.right)
        return max(left_max_depth, right_max_depth) + 1


print(Solution().maxDepth(createBiTree([3, 9, 20, None, None, 15, 7])))
Beispiel #7
0
    def findMode(self, root: TreeNode) -> List[int]:
        count = -1
        mode, mode_cnt = [], 0
        pre = None

        def dfs(root):
            if not root:
                return
            dfs(root.left)
            nonlocal count, pre, mode, mode_cnt
            if pre and pre.val == root.val:
                count += 1
            else:
                if count > mode_cnt:
                    mode, mode_cnt = [pre.val], count
                elif count == mode_cnt:
                    mode.append(pre.val)
                count = 1
            pre = root
            dfs(root.right)

        dfs(root)
        if count > mode_cnt:
            mode = [pre.val]
        elif count == mode_cnt:
            mode.append(pre.val)
        return mode


print(Solution().findMode(createBiTree([1, 1, 2, None, None, 2])))
Beispiel #8
0
# @Time : 2020/10/20 12:37
# @Author : LiuBin
# @File : 538.py
# @Description : 
# @Software: PyCharm
"""把二叉搜索树转换为累加树
关键字: 中序遍历
思路:
1、先右孩子、再左孩子
2、输入 当前状态作为入参,返回处理后的状态
"""
from utils import TreeNode, createBiTree


class Solution:
    def convertBST(self, root: TreeNode) -> TreeNode:
        def dfs(root, sum):
            if not root:
                return sum
            sum = dfs(root.right, sum)
            root.val += sum
            sum = dfs(root.left, root.val)
            return sum

        dfs(root, 0)
        return root


print(Solution().convertBST(createBiTree([4, 1, 6, 0, 2, 5, 7, None, None, None, 3, None, None, None, 8])))
Beispiel #9
0
# @Time : 2020/10/14 16:37
# @Author : LiuBin
# @File : 235.py
# @Description : 
# @Software: PyCharm
"""二叉搜索树的最近公共祖先
关键字: 前序遍历
"""
from utils import TreeNode, createBiTree


class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p, q) -> 'TreeNode':
        if p.val <= root.val <= q.val or q.val <= root.val <= p.val:
            return root
        if p.val < root.val:
            return self.lowestCommonAncestor(root.left, p, q)
        else:
            return self.lowestCommonAncestor(root.right, p, q)


print(Solution().lowestCommonAncestor(createBiTree([6, 2, 8, 0, 4, 7, 9, None, None, 3, 5]), TreeNode(2), TreeNode(8)))
Beispiel #10
0
    def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
        ret = []

        def dfs(root, sum, path):
            if not root:
                if sum == 0:
                    ret.append(path[:])
            elif root.left and root.right:
                sum -= root.val
                path.append(root.val)
                dfs(root.left, sum, path)
                dfs(root.right, sum, path)
                path.pop()
            else:
                sum -= root.val
                path.append(root.val)
                if root.left:
                    dfs(root.left, sum, path)
                else:
                    dfs(root.right, sum, path)
                path.pop()

        if not root:
            return []
        dfs(root, sum, [])
        return ret


print(Solution().pathSum(
    createBiTree([5, 4, 8, 11, None, 13, 4, 7, 2, None, None, 5, 1]), 22))
Beispiel #11
0
# @File : 563.py
# @Description :
# @Software: PyCharm
"""二叉树的坡度
关键字: 后序遍历
思路:
1、维护左右子树的和
2、累加当前节点的坡度
"""
from utils import TreeNode, createBiTree


class Solution:
    def findTilt(self, root: TreeNode) -> int:
        total_slope = 0

        def dfs(root):
            if not root:
                return 0
            l_sum = dfs(root.left)
            r_sum = dfs(root.right)
            nonlocal total_slope
            total_slope += abs(l_sum - r_sum)
            return l_sum + root.val + r_sum

        dfs(root)
        return total_slope


print(Solution().findTilt(createBiTree([1, 2, 3, 4, 5])))
Beispiel #12
0
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        d = {}
        max_ = 0

        def dfs(root):
            if not root:
                return 0
            sum = dfs(root.left) + root.val + dfs(root.right)
            if sum not in d:
                d[sum] = 0
            d[sum] += 1
            nonlocal max_
            max_ = max(d[sum], max_)
            return sum

        dfs(root)
        ret = []
        for k, v in d.items():
            if v == max_:
                ret.append(k)
        return ret


print(Solution().findFrequentTreeSum(createBiTree([5, 2, -3])))
Beispiel #13
0
# @Description :
# @Software: PyCharm
"""路径总和
关键字: 先序遍历
思路:
1、有一个特殊情况,就是给定的树是空树,且sum是0,需要返回False(题目限制)。
2、自顶向下缩小问题范围,sum -= root.val,最后到空节点应该等于0,否则分别继续向下探索
"""
from utils import TreeNode, createBiTree


class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        def dfs(root, sum):
            if not root:  # 此时必须保证是叶子节点
                return sum == 0
            elif root.right and root.left:
                sum -= root.val
                return dfs(root.left, sum) or dfs(root.right, sum)
            else:
                sum -= root.val
                return dfs(root.left, sum) if root.left else dfs(
                    root.right, sum)

        if not root:
            return False
        return dfs(root, sum)


print(Solution().hasPathSum(createBiTree([-2, None, -3]), -5))
Beispiel #14
0
            loc = []
            for i in left_loc + right_loc:
                s += 10**i * root.val
                loc.append(i + 1)
            return s + left_sum + right_sum, loc

        s, _ = dfs(root)
        return s

    def sumNumbers(self, root: TreeNode) -> int:
        ret = 0
        if not root:
            return 0

        def helper(path, node):
            nonlocal ret
            if not node.left and not node.right:
                ret += int(path)
                return

            if node.left:
                helper(path + str(node.left.val), node.left)
            if node.right:
                helper(path + str(node.right.val), node.right)

        helper(str(root.val), root)
        return ret


print(Solution().sumNumbers(createBiTree([4, 9, 0, 5, 1])))
Beispiel #15
0
# @File : 513.py
# @Description :
# @Software: PyCharm
"""找树左下角的值
关键字: 中序遍历
思路:
1、一旦进入更深层的树,更新第一个该深度遍历的节点即可
"""
from utils import TreeNode, createBiTree


class Solution:
    def findBottomLeftValue(self, root: TreeNode):
        ret, dep = None, 0

        def dfs(root, depth):
            if not root:
                return
            dfs(root.left, depth + 1)
            nonlocal ret, dep
            if depth > dep:
                ret, dep = root.val, depth
            dfs(root.right, depth + 1)

        dfs(root, 1)
        return ret


print(Solution().findBottomLeftValue(
    createBiTree([1, 2, 3, 4, 5, 6, None, None, 7])))
Beispiel #16
0
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        q = [root]
        ret = []
        depth = 1
        while q:
            size = len(q)
            if len(ret) < depth:
                ret.append([])
            for i in range(size):
                cur = q.pop(0)
                if depth % 2 == 1:
                    ret[depth - 1].append(cur.val)
                else:
                    ret[depth - 1].insert(0, cur.val)
                if cur.left: q.append(cur.left)
                if cur.right: q.append(cur.right)
            depth += 1

        return ret


print(Solution().zigzagLevelOrder(createBiTree([1, 2, None, 3, None, 4, 5])))
Beispiel #17
0
from utils import TreeNode, createBiTree


class Solution:
    def recoverTree(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        pre = s = t = None

        def dfs(root):
            if not root:
                return
            dfs(root.left)
            nonlocal s, t, pre
            if pre and pre.val > root.val:
                s = pre if not s else s
                t = root
            pre = root
            dfs(root.right)

        dfs(root)
        s.val, t.val = t.val, s.val


root = createBiTree(
    [68, 41, None, -85, None, -73, -49, -98, None, None, None, -124])
print(root)
Solution().recoverTree(root)
print(root)
Beispiel #18
0
# @Time : 2020/10/10 14:09
# @Author : LiuBin
# @File : 101.py
# @Description :
# @Software: PyCharm
"""对称二叉树
关键字: 反向先序遍历
目标: 验证一颗二叉树是不是镜面对称的二叉树
思路:
1、对同一棵树同时使用先序遍历
2、先序遍历的方向相反,一个先访问左孩子,然后右孩子,一个先访问右孩子,然后左孩子
3、这样的先序遍历的路径是镜像对称的,比较两个节点是否一样
"""
from utils import TreeNode, createBiTree


class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        def dfs(root1, root2):
            if not root1 and not root2:
                return True
            if root1 and root2 and root1.val == root2.val:
                return dfs(root1.left, root2.right) and dfs(
                    root1.right, root2.left)
            return False

        return dfs(root, root)


print(Solution().isSymmetric(createBiTree([1, 2, 2, None, 3, 3])))
Beispiel #19
0
# @Description : 
# @Software: PyCharm
"""二叉树的所有路径
关键字: 先序遍历
思路:
1、记录访问的路径
2、最后一步删除最前面的箭头
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        ret = []
        if not root:
            return []

        def dfs(root, path):
            if not root.left and not root.right:
                ret.append((path + "->" + str(root.val))[2:])
                return
            if root.left: dfs(root.left, path + "->" + str(root.val))
            if root.right: dfs(root.right, path + "->" + str(root.val))

        dfs(root, "")
        return ret


print(Solution().binaryTreePaths(createBiTree([1])))
Beispiel #20
0
# @Time : 2020/10/10 14:03
# @Author : LiuBin
# @File : 100.py
# @Description :
# @Software: PyCharm
"""相同的树
关键字: 先序遍历
思路:
1、同时遍历,同时比较两个节点
"""
from utils import TreeNode, createBiTree


class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and not q:
            return True
        if p and q and p.val == q.val:
            return self.isSameTree(p.left, q.left) and self.isSameTree(
                p.right, q.right)
        return False


a = createBiTree([1, None, 3, 2])
b = createBiTree([1, None, 3])
print(Solution().isSameTree(a, b))
Beispiel #21
0
# @Software: PyCharm
"""	在每个树行中找最大值
关键字: 任何遍历
思路:
1、维护每行的最大值数组,深度对应索引
"""
from utils import TreeNode, createBiTree
from typing import List


class Solution:
    def largestValues(self, root: TreeNode) -> List[int]:
        ret = []

        def dfs(root, depth):
            if not root:
                return
            nonlocal ret
            if len(ret) <= depth:
                ret.append(root.val)
            else:
                ret[depth] = max(ret[depth], root.val)
            dfs(root.left, depth + 1)
            dfs(root.right, depth + 1)

        dfs(root, 0)
        return ret


print(Solution().largestValues(createBiTree([1, 3, 2, 5, 3, None, 9])))
Beispiel #22
0
    def isValidBSTByInOrder(self, root: TreeNode) -> bool:
        def dfs(root):
            if not root:
                return
            if self.flag:
                dfs(root.left)
            if self.pre is not None and self.pre >= root.val:
                self.flag = False
            else:
                self.pre = root.val
            if self.flag:
                dfs(root.right)

        dfs(root)
        return self.flag

    def isValidBST(self, root: TreeNode) -> bool:
        def dfs(root, min_=float('-inf'), max_=float('inf')):
            if not root:
                return True
            if min_ >= root.val or max_ <= root.val or not dfs(
                    root.left, min_, root.val) or not dfs(
                        root.right, root.val, max_):
                return False
            return True

        return dfs(root)


print(Solution().isValidBST(createBiTree([1, 1])))
Beispiel #23
0
# @Author : LiuBin
# @File : 662.py
# @Description :
# @Software: PyCharm
"""二叉树最大宽度
关键字: 中序遍历
"""
from utils import TreeNode, createBiTree


class Solution:
    def widthOfBinaryTree(self, root: TreeNode) -> int:
        if not root:
            return 0
        q = [(root, 1)]
        width = 1
        while q:
            size = len(q)
            if size > 1:
                (s_root, s_no), (e_root, e_no) = q[0], q[-1]
                width = max(width, e_no - s_no + 1)
            for i in range(size):
                cur, no = q.pop(0)
                if cur.left: q.append((cur.left, no * 2 - 1))
                if cur.right: q.append((cur.right, no * 2))
        return width


print(Solution().widthOfBinaryTree(
    createBiTree([1, 3, 2, 5, None, None, 9, 6, None, None, 7])))
Beispiel #24
0
# @Time : 2020/10/14 17:40
# @Author : LiuBin
# @File : 236.py
# @Description :
# @Software: PyCharm
"""二叉树的最近公共祖先
关键字: 后序遍历
思路:
1、遇到直接返回找到的目标节点
2、如果左右子树各贡献了节点,那么最早遇到的父节点就是公共祖先
3、如果只有一个子树贡献节点,那么属于目标节点本身即是公共祖先。
"""
from utils import TreeNode, createBiTree


class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode',
                             q: 'TreeNode') -> 'TreeNode':
        if not root or root == q or root == p: return root
        l = self.lowestCommonAncestor(root.left, p, q)
        r = self.lowestCommonAncestor(root.right, p, q)

        if not l: return r
        if not r: return l
        return root


a = Solution().lowestCommonAncestor(
    createBiTree([-1, 0, 3, -2, 4, None, None, 8]), TreeNode(8), TreeNode(4))
print(a)
Beispiel #25
0
from utils import TreeNode, createBiTree


class Solution:
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        pre = None

        def dfs(root, parent):
            if not root:
                return
            dfs(root.right, root)
            dfs(root.left, root)
            nonlocal pre

            if parent:
                root.right = pre
                if parent.left is root:
                    parent.left = None
                    parent.right = root
            pre = root

        dfs(root, None)


root = createBiTree([3, 2])
Solution().flatten(root)
print(root)
Beispiel #26
0
            return 0
        return self.countNodesByDFS(root.left) + self.countNodesByDFS(
            root.right) + 1

    def countNodes(self, root: TreeNode) -> int:
        def dfs_left(root):
            if not root:
                return 0
            return dfs_left(root.left) + 1

        if not root:
            return 0

        depth = dfs_left(root)
        res = 0

        def dfs_right(root, curdep, idx):
            nonlocal depth, res
            if not root:
                return 0
            if curdep == depth:
                res = idx
            if not res: dfs_right(root.right, curdep + 1, 2 * idx + 1)
            if not res: dfs_right(root.left, curdep + 1, 2 * idx)

        dfs_right(root, 1, 1)
        return res


print(Solution().countNodes(createBiTree([1, 2, 3, 4, 5, 6, 7])))
Beispiel #27
0
关键字: 中序遍历
思路:
1、获得有序数列
2、维护最小的前后元素的差值
"""
from utils import TreeNode, createBiTree


class Solution:
    def getMinimumDifference(self, root: TreeNode):
        min_ = None
        last_val = None

        def dfs(root):
            if not root:
                return
            dfs(root.left)
            nonlocal min_, last_val
            if last_val is not None:
                if not min_ or root.val - last_val < min_:
                    min_ = root.val - last_val

            last_val = root.val
            dfs(root.right)

        dfs(root)
        return min_


print(Solution().getMinimumDifference(createBiTree([1, None, 5, 3])))
Beispiel #28
0
# @Time : 2020/10/15 16:00
# @Author : LiuBin
# @File : 226.py
# @Description : 
# @Software: PyCharm

"""翻转二叉树
关键字: 后序遍历
"""
from utils import TreeNode, createBiTree


class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return
        root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root


print(Solution().invertTree(createBiTree([1, 2, 3])))