【树-03】树的题目解析

目录

  1. 剑指 Offer 55 - II. 平衡二叉树/110. 平衡二叉树
  2. 剑指 Offer 26. 树的子结构 (中等难度)
  3. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
  4. 剑指 Offer 68 - II. 二叉树的最近公共祖先/236. 二叉树的最近公共祖先
  5. 剑指 Offer 36. 二叉搜索树与双向链表

一、剑指 Offer 55 - II. 平衡二叉树/110. 平衡二叉树

1.1 问题

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

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

3

/ \

9 20

/ \

15 7

返回 true

1.2 代码

class Solution:   #注意调用函数时,需要用self,若是嵌套类型的方法定义,则不需要

    def isBalanced(self, root: TreeNode) -> bool:

        if not root :return True

        if (abs(self.height(root.left)-self.height(root.right))>1):

            return False

        else:

            return self.isBalanced(root.left) and self.isBalanced(root.right)

    def height(self,root):

        if not root : return 0

        return 1max(self.height(root.left),self.height(root.right))

   

二、剑指 Offer 26. 树的子结构 (中等难度)

2.1 问题

输入两棵二叉树AB,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

BA的子结构, 即 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

2.2 代码(递归算法)

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 68 - I. 二叉搜索树的最近公共祖先

3.1 问题

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

百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 pq,最近公共祖先表示为一个结点 x,满足 x pq 的祖先且 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, 因为根据定义最近公共祖先节点可以为节点本身。

3.2 代码

class Solution:

    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':

        if not root :return None

        if p.val > q.val :  保证 p.val < q.val

            p,q = q,p

        while root :

            if root.val < p.val:  # p,q 都在 root 的右子树中

                root = root.right    遍历至右子节点

            if root.val > q.val:

                root = root.left

            else:

                break

        return root

四、剑指 Offer 68 - II. 二叉树的最近公共祖先/236. 二叉树的最近公共祖先

4.1 问题

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

百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 pq,最近公共祖先表示为一个结点 x,满足 x pq 的祖先且 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。因为根据定义最近公共祖先节点可以为节点本身。

4.2 理解

4.2 代码

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 # 1.

        if not left: return right # 3.

        if not right: return left # 4.

        return root # 2. if left and right:

五、剑指 Offer 36. 二叉搜索树与双向链表

5.1 问题

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

5.2 代码(中序遍历+递归)

大体思路要清楚:框架是中序遍历,写好中间部分即可:设置两个precurpre若为空,设置下头结点;不空,则进行互相指定。

不要忘记最后的head与最后的指定。

"""

# Definition for a Node.

class Node:

    def __init__(self, val, left=None, right=None):

        self.val = val

        self.left = left

        self.right = right

"""

class Solution:

    def treeToDoublyList(self, root: 'Node') -> 'Node':

        def dfs(cur):

            if not cur :return

            dfs(cur.left)

            if self.pre:  #不为空,则互相指定

                self.pre.right,cur.left = cur ,self.pre

            else:  #为空,记录头结点,这个走一遍

                self.head = cur

            self.pre = cur  #保存后进行下一步推进

            dfs(cur.right)

        if not root :return

        self.pre = None

        dfs(root)

        self.head.left,self.pre.right = self.pre,self.head

        return self.head

参考文献

1https://leetcode-cn.com/

posted @ 2020-08-15 22:49  忆凡人生  阅读(182)  评论(0编辑  收藏  举报