栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【20220701Leetcode-04】【树】

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【20220701Leetcode-04】【树】

20220701Leetcode-04【树】

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二十七、剑指 Offer 27. 二叉树的镜像【复盘】

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

例如输入:
4
/
2 7
/ /
1 3 6 9

镜像输出:
4
/
7 2
/ /
9 6 3 1

示例 1:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

限制:0 <= 节点个数 <= 1000

二叉树镜像定义: 对于二叉树中任意节点 rootroot ,设其左 / 右子节点分别为 left, rightleft,right ;则在二叉树的镜像中的对应 rootroot 节点,其左 / 右子节点分别为 right, leftright,left 。

递归法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

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

辅助栈(或队列)

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root: return
        stack = [root]
        while stack:
            node = stack.pop()
            if node.left: stack.append(node.left)
            if node.right: stack.append(node.right)
            node.left, node.right = node.right, node.left
        return root
二十八、剑指 Offer 28. 对称的二叉树【复盘】

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/
2 2
/ /
3 4 4 3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
1
/
2 2

3 3

示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false

限制:0 <= 节点个数 <= 1000

对称二叉树定义: 对于树中 任意两个对称节点 LL 和 RR ,一定有:
L.val = R.valL.val=R.val :即此两对称节点值相等。
L.left.val = R.right.valL.left.val=R.right.val :即 LL 的 左子节点 和 RR 的 右子节点 对称;
L.right.val = R.left.valL.right.val=R.left.val :即 LL 的 右子节点 和 RR 的 左子节点 对称。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        def recur(L,R):
            if not L and not R:
                return True
            if not L or not R or L.val!=R.val:
                return False
            return recur(L.left,R.right) and recur(L.right,R.left)
        
        if root:
            return recur(root.left,root.right)
        else:
            return True
二十九、剑指 Offer 32 - I. 从上到下打印二叉树【层序遍历BFS】

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/
9 20
/
15 7

返回:
[3,9,20,15,7]

提示:节点总数 <= 1000

  • 题目要求的二叉树的 从上至下 打印(即按层打印),又称为二叉树的 广度优先搜索(BFS)。
  • BFS 通常借助 队列 的先入先出特性来实现。

从上至下按层打印,同层节点从左至右打印。

层序遍历模板

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrder(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        queue = [root]
        res = []
        while queue:
            node = queue.pop(0)
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return res

Python collextions

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrder(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        res,queue=[],collections.deque()
        queue.append(root)
        while queue:
            node=queue.popleft()
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return res

Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 修改完的代码如下:

class Solution {
    public int[] levelOrder(TreeNode root) {
        if (root == null) // 空树则返回空数组
            return new int[0];
        Queue q = new LinkedList<> (); // 借助一个队列,通过 BFS 实现按层遍历二叉树
        ArrayList tmp =new ArrayList<> (); // 申请一个动态数组 ArrayList 动态添加节点值
        
        q.offer(root); // 根结点先入队
        while (q.size() != 0) {
            TreeNode node = q.poll(); // 取出当前队首元素
            tmp.add(node.val); 
            if(node.left != null) q.offer(node.left); // 左子节点入队
            if(node.right != null) q.offer(node.right); // 右子节点入队
        }

        // 将 ArrayList 转为 int数组并返回
        int[] res = new int[tmp.size()];
        for (int i=0; i
            res[i] = tmp.get(i);
        }
        return res;
    }
}

Python collextions

namedtuple() 命名元组

import collections

point = collections.namedtuple('Points', ['x', 'y'])
p1 = point(2, 3)
p2 = point(4, 2)

print(p1) # Points(x=2, y=3)
print(p2) # Points(x=4, y=2)

p1._replace(x=5)
print(p1) # Points(x=5, y=3)

deque() 双端队列

from collections import deque

q = deque(['a', 'b', 'c'], maxlen=10)
# 从右边添加一个元素
q.append('d')
print(q) # deque(['a', 'b', 'c', 'd'], maxlen=10)

# 从左边删除一个元素
print(q.popleft()) # a
print(q) # deque(['b', 'c', 'd'], maxlen=10)

# 扩展队列
q.extend(['i', 'j'])
print(q) # deque(['b', 'c', 'd', 'i', 'j'], maxlen=10)

# 查找下标
print(q.index('c')) # 1

# 移除第一个'd'
q.remove('d')
print(q) # deque(['b', 'c', 'i', 'j'], maxlen=10)

# 逆序
q.reverse()
print(q) # deque(['j', 'i', 'c', 'b'], maxlen=10)

# 最大长度
print(q.maxlen) # 10

————————————————
版权声明:本文为CSDN博主「Python热爱者」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qdpython/article/details/120786550

二十九、剑指 Offer 32 - II. 从上到下打印二叉树 II【每一层打印到一行】

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/
9 20
/
15 7

返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]

提示:节点总数 <= 1000

I. 按层打印: 题目要求的二叉树的 从上至下 打印(即按层打印),又称为二叉树的 广度优先搜索(BFS)。BFS 通常借助 队列 的先入先出特性来实现。
II. 每层打印到一行: 将本层全部节点打印到一行,并将下一层全部节点加入队列,以此类推,即可分为多行打印。

Python collections 中的双端队列 deque()

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res,queue=[],collections.deque()
        queue.append(root)
        while queue:
            tmp=[]
            for _ in range(len(queue)):
                node=queue.popleft()
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(tmp)
        return res
三十、剑指 Offer 54. 二叉搜索树的第k大节点【二叉搜索树中序遍历】

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/
1 4

2
输出: 4

示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/
3 6
/
2 4
/
1
输出: 4

限制:1 ≤ k ≤ 二叉搜索树元素个数

二叉搜索树的中序遍历是:左=>根=>右; 二叉搜索树的中序遍历从小到大是有序的

中序遍历

def dfs(root):
	if not root:
		return
	dfs(root.left)
	print(root.val)
	dfs(root.right)

中序遍历倒序

def dfs(root):
	if not root:
		return
	dfs(root.right)
	print(root.val)
	dfs(root.left)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        def dfs(root):
            if not root: return
            dfs(root.right)
            if self.k == 0: return
            self.k -= 1
            if self.k == 0: self.res = root.val
            dfs(root.left)

        self.k = k
        dfs(root)
        return self.res
三十一、剑指 Offer 55 - I. 二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回它的最大深度 3 。

提示:节点总数 <= 10000

在这里插入代码片
三十二、剑指 Offer 55 - II. 平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/
9 20
/
15 7
返回 true 。

示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/
2 2
/
3 3
/
4 4
返回 false 。

限制:0 <= 树的结点个数 <= 10000

树的遍历方式总体分为两类:
深度优先搜索(DFS):先序遍历、中序遍历、后序遍历;
广度优先搜索(BFS):层序遍历
求树的深度需要遍历树的所有节点

后序遍历(DFS)
树的后序遍历 / 深度优先搜索往往利用 递归 或 栈 实现
树的深度 等于 左子树的深度 与 右子树的深度 中的 最大值 +1+1

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

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

层序遍历(BFS)
树的层序遍历 / 广度优先搜索往往利用 队列 实现
每遍历一层,则计数器 +1+1 ,直到遍历完成,则可得到树的深度

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        queue,res=[root],0
        while queue:
            tmp=[]
            for node in queue:
                if node.left:
                    tmp.append(node.left)
                if node.right:
                    tmp.append(node.right)
            queue=tmp
            res+=1
        return res

平衡二叉树(AVL):
它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。

后序遍历+剪枝(从底至顶):
对二叉树做后序遍历,从底至顶返回子树深度,若判定某子树不是平衡树则 “剪枝” ,直接向上返回。

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

先序遍历 + 判断深度 (从顶至底):

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if not root: return True
        return abs(self.depth(root.left) - self.depth(root.right)) <= 1 and 
            self.isBalanced(root.left) and self.isBalanced(root.right)

    def depth(self, root):
        if not root: return 0
        return max(self.depth(root.left), self.depth(root.right)) + 1
三十三、剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]


示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        while root:
            if root.val < p.val and root.val p.val and root.val > q.val:
                root=root.left
            else:
                break
        return root

祖先的定义: 若节点 p 在节点 root 的左(右)子树中,或 p = root,则称 root 是 p 的祖先。
最近公共祖先的定义: 设节点 root 为节点 p,q 的某公共祖先,若其左子节点 root.left 和右子节点 root.right 都不是 p,q 的公共祖先,则称 root 是 “最近的公共祖先” 。

二叉搜索树

二叉搜索树又称为二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有结点的值都小于根结点的值。
  • 若它的右子树不为空,则右子树上所有结点的值都大于根结点的值。
  • 它的左右子树也分别是二叉搜索树。
三十四、剑指 Offer 68 - II. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        if not root or root==p or root==q:
            return root
        left=self.lowestCommonAncestor(root.left,p,q)
        right=self.lowestCommonAncestor(root.right,p,q)
        if not left and not right:
            return
        if not left:
            return right
        if not right:
            return left
        return root
三十五、剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

示例 1:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]

限制:0 <= 节点个数 <= 5000

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        def recur(root, left, right):
            if left > right: return                               # 递归终止
            node = TreeNode(preorder[root])                       # 建立根节点
            i = dic[preorder[root]]                               # 划分根节点、左子树、右子树
            node.left = recur(root + 1, left, i - 1)              # 开启左子树递归
            node.right = recur(i - left + root + 1, i + 1, right) # 开启右子树递归
            return node                                           # 回溯返回根节点

        dic, preorder = {}, preorder
        for i in range(len(inorder)):
            dic[inorder[i]] = i
        return recur(0, 0, len(inorder) - 1)
三十六、剑指 Offer 26. 树的子结构

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:
3
/
4 5
/
1 2

给定的树 B:
4
/
1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例 1:
输入:A = [1,2,3], B = [3,1]
输出:false

示例 2:
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
限制:0 <= 节点个数 <= 10000

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
        
class Solution:
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        def recur(A, B):
            if not B: return True
            if not A or A.val != B.val: return False
            return recur(A.left, B.left) and recur(A.right, B.right)

        return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))
三十七、剑指 Offer 33. 二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5
/
2 6
/
1 3

示例 1:
输入: [1,6,3,2,5]
输出: false

示例 2:
输入: [1,3,2,6,5]
输出: true

提示:
数组长度 <= 1000

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1002096.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号