树的总结(算法)

树的总结(算法)

总的来说树需要掌握的由一下几点:
1、树的遍历方式:前序(根左右),中序(左根右,二叉搜索树中序遍历必有序),后序(左右根),层序(一个列表,多个列表,之字形)
2、树的递归
3、树的迭代(利用栈来实现)
4、树的创建(列表或者是字典)
5、树的动态规划(动态规划里面再讲)

下面就具体的一些题目来说一下。
首先放一下树递归的GIF图(来自leetcode的一个大佬制作的)
在这里插入图片描述
上面这个图是递归的基础,必须牢记。

我自己总结了一下相应的树的算法。仅供参考。

代码都是用python3写的,基本上都是leetcode的题目。
这里是代码链接结合代码再看下面的总结会大有帮助的。(可以帮忙点个小星星)

总结:

其实说白了,二叉树也就是4种遍历方式,外加列表存储一下树节点,重要的是弄懂树的递归是怎么一回事。

1、重建二叉树:题目给出的是: 先序+中序 或者是 层序+中序 解题思路:根据题中所给的序列分别构造相应的左右子树序列,然后左右分别递归,注意在递归出口节点创建树节点。

2、树的子结构:解题思路:先判断根节点值是否相等,然后再判断下面的结构是否相等,若根节点值不相等,则判断左子树和右子树是否与子结构相等 子函数(判断树中元素是否相等):子结构为空返回True,树为空返回False,然后判断各个位置的值是否相等。(子函数返回True或者False的,一般递归出现在最后的return条件)

3、二叉树的镜像: 解题思路:交换左右子树的值 然后分别递归左右子树(也就是左右子树分别交换)

4、判断是否是对称的二叉树(也就是镜像二叉树): 解题思路:比较左右子树 子函数:先判断左右子树均为空返回True 有一个为空返回False ,然后再比较根节点的值,若相等接着递归比较左右,右

5、从上往下打印二叉树: 解题思路:先把数放入列表中,方便索引。 当列表不为空的时候,若根节点存在左节点则把左节点放入树列表的后面,同理右节点也是。然后保存根节点的值,同时pop出根节点。

6、从上往下按行打印二叉树:解题思路:与上面的不同就是要建立一个临时列表list1保存根节点的值,还有建立一个临时列表list2保存子节点的值,循环完根节点列表以后,用临时列表list1保存根节点的值同时把list2中的子节点的值赋值给根节点列表,再次循环。(其实这就是二叉树的层序遍历)

15、之字形打印二叉树: 解题思路:利用一个标志变量flag来标记从左往右还是从右往走,然后就是利用栈和flag=1的时候反向储存节点值,实现。

7、判断数组是否是二叉搜索树的后序遍历序列:解题思路:后续遍历的特点就是最后一个节点是根节点。然后二叉搜索树的特点就是左子树小于根节点的值,右子树大于根节点的值。所以我们的解题思路就是先分割左右子树,然后判断左右子树是否满足二叉搜索树的条件,然后分别递归左右子树。

8、二叉树中和为某一值(k)的路径(路径总和二): 解题思路:先创建一个类变量sum用于存放求和值。再创建一个列表self.a存放路径中的数值。若sum==k且左右子树均为空,self.b.append(self.a[:]),若sum小于k,递归左右子树,否则(大于k)sum -=self.a[-1],self.a.pop()

16、路径总和:因为是返回True或False所以return 递归。

9、二叉搜索树转化为双向链表: 解题思路:先递归转化左子树,在把左子树的最右边一个节点链接到根节点上(双向链接),同理右子树,然后从根节点向前寻找头结点,返回头结点的地址

24、二叉树展开为链表:先找到左子树的最右边节点,然后将右节点挂在左子树的最右边节点上,最后再把整个左子树挂在根节点的右边。然后后序遍历二叉树。

10、二叉树的最大深度: 解题思路:(1)后序遍历,返回左右子树的最大值+1 (2)按层向下检索,与2,5相似

23、二叉树的最小深度:与上相似,区别在于添加一个判断左节点或右节点为空,然后返回left+right+1.

11、平衡二叉树: 解题思路:后序遍历,判断左右子树长度差。(这里有一个编程小技巧,建立一个类变量,用于子函数在递归过程中返回True或False。满足条件立即保存状态。)

12、二叉搜索树的第K个节点: 解题思路:中序遍历

13、二叉树的下一个节点: 解题思路:两条路径,(1)若此节点的右子树存在,则递推返回右子树的最左节点。(2)若此节点的下一个节点是是根节点,若根节点的左节点==此节点,则返回根节点,否则继续向上递推根节点。

14、序列化二叉树: 解题思路:序列化:若空==‘#’然后中序遍历 反序列化:建立一个标志位用来索引序列列表。若非空,赋值root,递归root.left 和 root.right(其实序列化就是二叉树的前序遍历,反序列化就是前序重建二叉树)

17、二叉树的中序遍历、后序遍历:迭代法遍历二叉树,用颜色标记走过的节点位,然后用栈来实现遍历。

18、验证二叉搜索树:根据二叉搜索树的性质给出递归的出口条件,然后递归验证左右子树(注意递归左右子树传入的值,左子树的left=left,right=root.val,右子树的left=root.val,right=right)

19、恢复二叉搜索树:跟上面一样,多了一个交换节点值的步骤。

20、相同的树:因为是返回True或False所以return 递归。

21、将有序数组转为二叉搜索树:实际上就是中序遍历转二叉搜索树,因为不是唯一的,所以取中间元素作为根节点,左边就是左子树,右边就是右子树。

22、合法的二叉搜索树:递归:上面判断条件return进行递归 中序遍历:中序遍历二叉搜索树天然有序!!

25、节点与其祖先的最大差值:子函数寻找最大最小值

26、累加树:因为是二叉搜索树,所以中序遍历的反向就是从大到小排序(右中左),然后累加节点值更新下一节点值。

27、填充每个节点的下一个右节点指针:构造条件(左节点存在,则左节点的next指向右节点,next节点存在,则有节点的next指向next的左节点)+递归

28、填充每个节点的下一个右节点指针2:子函数寻找next节点的最左节点,主函数判断连接情况以后再递归(先右后左,因为有右边才有左边)

29、求根到叶子结点的数字和:简单条件加递归,注意找回递归根节点的值。

30、二叉搜索树的迭代器:迭代搜索树

31、二叉树的右视图:层序遍历

32、二叉搜索树中第k小元素:迭代法:利用栈保存树,中序遍历

33、二叉树的最近公共祖先:遍历查找,左没有就在右,右没有就在左,都有就在root

34、从先序遍历还原二叉树:用字典保存二叉树节点。遍历先序数组,保存字符和相应的深度,然后传入子函数建立树

35、字典树:用字典保存树儿子节点,字典嵌套。

字典树

class TrieNode():
    def __init__(self,value,count):
        self.value = value
        self.count = count
        self.children = {}

class Trie():

    def __init__(self):
        self.root = TrieNode(value = None,count = 0)
    
    def build(self,words):

        cur_node = self.root
        for item in words:
            if item not in cur_node.children:
                child = TrieNode(value=item,count=0)
                cur_node.children[item] = child
                cur_node = child
            else:
                cur_node = cur_node.children[item]
                cur_node.count +=1
    def search(self,test_word):
        cur_node = self.root
        mark = True
        for item in test_word:
            if item not in cur_node.children:
                mark = False
                break
            else:
                cur_node = cur_node.children[item]
        if cur_node.children:
            mark = False
        return mark
                


if __name__ == '__main__':
    trie = Trie()
    texts = ['what','rank','range','water','want','ranker','rant']
    for text in texts:
        trie.build(text)

    markx = trie.search('what')
    print(markx)

leetcode 24 二叉树和为某一值得路径(考察树的递归,注意最后的返回初始值)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    
    def __init__(self):
        self.sumc = 0
        self.a = []
        self.b = []
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        # write code here
        if not root:
            return []
        self.sumc += root.val
        self.a.append(root.val)
        if self.sumc == expectNumber and not root.left and not root.right:
            self.b.append(self.a[:])
		#若是有负数的话,则直接改为else
        elif self.sumc < expectNumber:
            self.FindPath(root.left,expectNumber)
            self.FindPath(root.right,expectNumber)
        self.sumc -=self.a[-1]
        self.a.pop()
        return self.b
                

94 二叉树的中序遍历(非递归版本)利用标定状态和栈来实现,有点像层序遍历

#
# @lc app=leetcode.cn id=94 lang=python3
#
# [94] 二叉树的中序遍历
#

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

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        WHITE, GRAY = 0, 1
        res = []
        stack = [(WHITE, root)]
        while stack:
            color, node = stack.pop()
            if node is None: continue
            if color == WHITE:
                stack.append((WHITE, node.right))
                stack.append((GRAY, node))
                stack.append((WHITE, node.left))
            else:
                res.append(node.val)
        return res
        
# @lc code=end

100 相同的数

# @before-stub-for-debug-begin
from python3problem100 import *
from typing import *
# @before-stub-for-debug-end

#
# @lc app=leetcode.cn id=100 lang=python3
#
# [100] 相同的树
#

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

'''
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

输出: true
示例 2:

输入:      1          1
          /           \
         2             2

        [1,2],     [1,null,2]

输出: false
'''
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and not q:
            return True
        if not p or not q:
            return False
        if p.val != q.val:
            return False
        return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
# @lc code=end


102 二叉树的层序遍历和之字形遍历

#
# @lc app=leetcode.cn id=102 lang=python3
#
# [102] 二叉树的层序遍历
#

# @lc code=start
# 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 []
        queue = [root]
        res = []
        while queue:
            cur = []
            nextqueue = []
            for i in queue:
                cur.append(i.val)
                if i.left:
                    nextqueue.append(i.left)
                if i.right:
                    nextqueue.append(i.right)
            queue = nextqueue
            res.append(cur)
        return res
#
# @lc app=leetcode.cn id=103 lang=python3
#
# [103] 二叉树的锯齿形层次遍历
#

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


class Solution:
    # 层次遍历思想,栈实现逆序,精妙
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []
        stack = [root]
        flag = 0
        while stack:
            tmp = []
            new_stack = []
            while stack:
                #精华,栈是逆序,所以就有了逆逆为正,正逆为逆。
                cur = stack.pop()
                tmp.append(cur.val)
                if flag ==0:
                    if cur.left:
                        new_stack.append(cur.left)
                    if cur.right:
                        new_stack.append(cur.right)
                else:
                    if cur.right:
                        new_stack.append(cur.right)
                    if cur.left:
                        new_stack.append(cur.left)
            res.append(tmp)
            stack = new_stack
            flag = 1-flag
        return res

# @lc code=end


104 二叉树的最大深度

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

平衡二叉树(在求二叉树深度的基础上定义了一个全局变量self.res用来及时记录递归中不符合条件的状态)

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if not root:
            return True
        self.res = True
        self.helper(root)
        return self.res
    def helper(self,root):
        if not root:
            return 0
        left = self.helper(root.left)
        right = self.helper(root.right)
        if abs(left-right) >1:
            self.res = False
            return False
        return max(left,right)+1

返回二叉树的最小深度(注意只有一条子树的情况)

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        left = self.minDepth(root.left)
        right = self.minDepth(root.right)
        #返回左节点或右节点为空的情况,也就是其中一个节点为0
        if not left or not right:
            return left+right+1
        return min(left,right)+1

路径总和

class Solution:
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False

        sum -= root.val
        if not root.left and not root.right:  # if reach a leaf
            return sum == 0
        return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum)

路径总和2,求出每条路径(类似于回溯)

class Solution:
    def __init__(self):
        self.res = 0
        self.a = []
        self.b = []
    def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
        if not root:
            return []
        val = root.val
        self.a.append(val)
        self.res +=val
        if sum==self.res and not root.left and not root.right:
            self.b.append(self.a[:])
        else:
            self.pathSum(root.left,sum)
            self.pathSum(root.right,sum)
        self.res -= self.a[-1]
        self.a.pop()
        return self.b

二叉树展开为链表()

class Solution:
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if not root:
            return None
        if root.left:
            #找到左子树的最右边节点
            pre = root.left
            while pre.right:
                pre = pre.right
            #将右节点挂在左子树的最右边节点上
            pre.right = root.right
            #再将整个左子树挂在根节点的右边
            root.right = root.left
            root.left = None
        #上面就排好了右子树的一个节点,然后遍历右子树即可
        self.flatten(root.right)

指向下一个节点的右侧节点(完全二叉树)(也就是每个子节点横向连接)

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
        if root.left:
            root.left.next = root.right
            if root.next:
                root.right.next = root.next.left
        self.connect(root.left)
        self.connect(root.right)
        return root

指向下一个节点的右侧节点(非完全二叉树)

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        def helper(root):
            while root.next:
                if root.next.left:
                    return root.next.left
                elif root.next.right:
                    return root.next.right
                root = root.next
            return None
        if not root or (not root.left and not root.right):
            return root
        if root.left and root.right:
            root.left.next = root.right
            root.right.next = helper(root)
        if root.left and not root.right:
            root.left.next = helper(root)
        if root.right and not root.left:
            root.right.next = helper(root)
        #先递归右子树再递归左子树,因为有右才有左!!!
        self.connect(root.right)
        self.connect(root.left)
        return root

105 从前序与中序遍历构造二叉树

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder)==0:
            return None
        if len(preorder)==1:
            return TreeNode(preorder[0])
        left_pre = preorder[1:inorder.index(preorder[0])+1]
        right_pre = preorder[inorder.index(preorder[0])+1:]
        left_in = inorder[:inorder.index(preorder[0])]
        right_in = inorder[inorder.index(preorder[0])+1:]

        root = TreeNode(preorder[0])
        root.left = self.buildTree(left_pre,left_in)
        root.right = self.buildTree(right_pre,right_in)
        return root

二叉树中的最大路径和(路径是指能连在一起的节点,但是不能相交)

class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        self.max_num = -20
        self.find(root)
        return self.max_num
    def find(self,node):
        if not node:
            return 0
        left = max(0,self.find(node.left))
        right = max(0,self.find(node.right))
        #这里由于node.val+left+right一定大于node.val+max(left,right)这种情况,所以省略。
        self.max_num = max(self.max_num,node.val+left+right)
        return node.val+max(left,right)#向上面的父节点递归

求根到叶子节点的数字和(回溯思想)

class Solution:
    def __init__(self):
        self.temp = 0
        self.res = []
    def sumNumbers(self, root: TreeNode) -> int:
        if not root:
            return 0
        self.temp = self.temp*10 + root.val
        self.sumNumbers(root.left)
        self.sumNumbers(root.right)
        if not root.left and not root.right:
            self.res.append(self.temp)
        self.temp = (self.temp - root.val)//10
        return sum(self.res)

二叉搜索树迭代器

class BSTIterator:

    def __init__(self, root: TreeNode):
        self.stack = []
        self.left_search(root)

    def left_search(self,root):
        while root:
            self.stack.append(root)
            root = root.left

    def next(self) -> int:
        """
        @return the next smallest number
        """
        node = self.stack.pop()
        if node.right:
            self.left_search(node.right)
        return node.val


    def hasNext(self) -> bool:
        """
        @return whether we have a next smallest number
        """
        return len(self.stack)>0

翻转二叉树

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

二叉树的所有路径

class Solution:
    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        paths = []
        def helper(root,path):
            if root:
                path +=str(root.val)
                if not root.left and not root.right:
                    paths.append(path)
                else:
                    path +='->'
                    helper(root.left,path)
                    helper(root.right,path)

        helper(root,'')   
        return paths   

二叉树的序列化与反序列化

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.
        
        :type root: TreeNode
        :rtype: str
        """
        def helper(root,path):
            if not root:
                path +='None,'
            else:
                path +=str(root.val) + ','
                path = helper(root.left,path)
                path = helper(root.right,path)
            return path
        return helper(root,'')
        
    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        def rhelper(l):
            if l[0] == 'None':
                l.pop(0)
                return None
            root = TreeNode(l[0])
            l.pop(0)
            root.left = rhelper(l)
            root.right = rhelper(l)
            return root
        data_list = data.split(',')
        root = rhelper(data_list)
        return root

节点与其祖先的最大差值

class Solution:
    def maxAncestorDiff(self, root: TreeNode) -> int:
        if not root:
            return None
        self.res = 0
        self.search(root,root.val,root.val)
        return self.res

    def search(self,root,maxroot,minroot):
        if not root:
            return
        self.res = max(self.res,max(abs(maxroot-root.val),abs(minroot-root.val)))
        if maxroot < root.val:
            maxroot = root.val
        if minroot > root.val:
            minroot = root.val
        self.search(root.left,maxroot,minroot)
        self.search(root.right,maxroot,minroot)
        return maxroot,minroot

二叉搜索树需要掌握的三个点:

1、二叉搜索树的中序遍历的序列是递增排序的序列。中序遍历的遍历次序:Left -> Node -> Right。

def inorder(root):
    return inorder(root.left) + [root.val] + inorder(root.right) if root else []

2、Successor 代表的是中序遍历序列的下一个节点。即比当前节点大的最小节点,简称后继节点。 先取当前节点的右节点,然后一直取该节点的左节点,直到左节点为空,则最后指向的节点为后继节点。

def successor(root):
    root = root.right
    while root.left:
        root = root.left
    return root

3、Predecessor 代表的是中序遍历序列的前一个节点。即比当前节点小的最大节点,简称前驱节点。先取当前节点的左节点,然后取该节点的右节点,直到右节点为空,则最后指向的节点为前驱节点。

def predecessor(root):
    root = root.left
    while root.right:
        root = root.right
    return root

例题:450、删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
示例:
root = [5,3,6,2,4,null,7]
key = 3
5
/
3 6
/ \
2 4 7
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
5
/
4 6
/
2 7
另一个正确答案是 [5,2,6,null,4,null,7]。
5
/
2 6
\
4 7

class Solution:
    def successor(self, root):
        """
        One step right and then always left
        """
        root = root.right
        while root.left:
            root = root.left
        return root.val
    
    def predecessor(self, root):
        """
        One step left and then always right
        """
        root = root.left
        while root.right:
            root = root.right
        return root.val
        
    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if not root:
            return None
        
        # delete from the right subtree
        if key > root.val:
            root.right = self.deleteNode(root.right, key)
        # delete from the left subtree
        elif key < root.val:
            root.left = self.deleteNode(root.left, key)
        # delete the current node
        else:
            # the node is a leaf
            if not (root.left or root.right):
                root = None
            # the node is not a leaf and has a right child
            elif root.right:
                root.val = self.successor(root)
                root.right = self.deleteNode(root.right, root.val)
            # the node is not a leaf, has no right child, and has a left child    
            else:
                root.val = self.predecessor(root)
                root.left = self.deleteNode(root.left, root.val)
                        
        return root
        

96 不同的二叉搜索树 (动态规划计算树)

#
# @lc app=leetcode.cn id=96 lang=python3
#
# [96] 不同的二叉搜索树
#
'''
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

示例:

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3
'''
# @lc code=start
class Solution:
    def numTrees(self, n: int) -> int:
        #dp[n]的含义是n个值的不同二叉搜索树的数量
        dp = [0]*(n+1)
        dp[0]=dp[1]=1
        for j in range(2,n+1):
            for i in range(1,j+1):
                #i前面的全排列与i后面的全排列的积,叠加起来
                dp[j] += dp[i-1]*dp[j-i]
        return dp[-1]

# @lc code=end


95 不同的二叉搜索树(遍历并创建树)

# @before-stub-for-debug-begin
from python3problem95 import *
from typing import *
# @before-stub-for-debug-end

#
# @lc app=leetcode.cn id=95 lang=python3
#
# [95] 不同的二叉搜索树 II
#

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

class Solution:
    def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        def generate_trees(start, end):
            if start > end:
                return [None,]
            
            all_trees = []
            for i in range(start, end + 1):  # pick up a root
                # all possible left subtrees if i is choosen to be a root
                left_trees = generate_trees(start, i - 1)
                
                # all possible right subtrees if i is choosen to be a root
                right_trees = generate_trees(i + 1, end)
                
                # connect left and right subtrees to the root i
                for l in left_trees:
                    for r in right_trees:
                        current_tree = TreeNode(i)
                        current_tree.left = l
                        current_tree.right = r
                        all_trees.append(current_tree)
            
            return all_trees
        
        return generate_trees(1, n) if n else []

class Solution:
    def generateTrees(self, n: int):
        if n == 0:
            return None
        # 对dp进行初始化
        dp = []
        for i in range(0, n+1):   # 初始化dp
            dp.append([])
            for j in range(0, n+1):
                if i == j:
                    dp[i].append([TreeNode(i)])
                elif i < j:
                    dp[i].append([])
                else:
                    dp[i].append([None])
        dp[0][0] = [None]
        for i in range(n-1, 0, -1):  # 自下向上进行循环
            for j in range(i+1, n+1):
                for r in range(i, j+1):   # i-j每一个节点为顶点的情况
                    left = r+1 if r < j else r    # 右边的值需要边界判断,不然会溢出数组
                    for x in dp[i][r-1]:          # 左右子树排列组合   
                        for y in dp[left][j]:
                            node = TreeNode(r)     
                            node.left = x
                            node.right = y
                            if r == j:
                                node.right = None
                            dp[i][j].append(node)      # dp[i][j]添加此次循环的值
        return dp[1][n]
# @lc code=end

98 验证二叉搜索树

# @before-stub-for-debug-begin
from python3problem98 import *
from typing import *
# @before-stub-for-debug-end

#
# @lc app=leetcode.cn id=98 lang=python3
#
# [98] 验证二叉搜索树
#

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

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        def helper(root,left=float('-inf'),right=float('inf')):
            if not root:
                return True
            if root.val<=left or root.val >=right:
                return False
            if not helper(root.left,left,root.val):
                return False
            if not helper(root.right,root.val,right):
                return False  
            return True
        return helper(root)
        
# @lc code=end


99 恢复二叉搜索树

#
# @lc app=leetcode.cn id=99 lang=python3
#
# [99] 恢复二叉搜索树
#

# @lc code=start
# 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 recoverTree(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        def helper(root,low=float('-inf'),unper=float('inf')):
            if not root:
                return None
            val = root.val
            if root.right and val>=unper:
                root,root.right = root.right,root
            if root.left and val <=low:
                root,root.left = root.left,root
            helper(root.left,low,val)
            helper(root.right,val,unper)
            return root
        return helper(root)
        
# @lc code=end


二叉搜索树中第K小的数(先找到最左节点,然后向上回溯找右节点,这样就是从小到大遍历了)

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.stack = []
        while True:
            while root:
                self.stack.append(root)
                root = root.left
            root = self.stack.pop()
            k -=1
            if not k:
                return root.val
            root = root.right   

二叉搜索树的最近公共祖先(三种情况,左右子树各一个,那么返回根节点,都在左子树或右子树,那么递归的left或right就会有值,返回root即可)

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # if p.val < root.val and q.val < root.val:
        #     return self.lowestCommonAncestor(root.left,p,q)
        # elif p.val > root.val and q.val > root.val:
        #     return self.lowestCommonAncestor(root.right,p,q)
        # else:
        #     return root
        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: return right
        if not right: return left
        return root

二叉搜索树与双向链表

class Solution:
    def Convert(self, pRootOfTree):
        if not pRootOfTree:
            return pRootOfTree
        if not pRootOfTree.left and not pRootOfTree.right:
            return pRootOfTree
        # 处理左子树
        self.Convert(pRootOfTree.left)
        left=pRootOfTree.left
 
        # 连接根与左子树最大结点
        if left:
            while(left.right):
                left=left.right
            pRootOfTree.left,left.right=left,pRootOfTree
 
        # 处理右子树
        self.Convert(pRootOfTree.right)
        right=pRootOfTree.right
 
        # 连接根与右子树最小结点
        if right:
            while(right.left):
                right=right.left
            pRootOfTree.right,right.left=right,pRootOfTree
        #找到双向链表的表头
        while(pRootOfTree.left):
            pRootOfTree=pRootOfTree.left
        return pRootOfTree
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值