牛客网-剑指offer-树-第二部分

JZ36 二叉搜索树与双向链表
解法1:进行二叉树的中序遍历,并将遍历结果存储到数组中,再对数组进行遍历生成双向链表
在这里插入图片描述

class Solution:
    def Convert(self , pRootOfTree ):
        # write code here
        if not pRootOfTree:
            return
        res = []
        
        def order(root, res):
            if root.left:
                order(root.left, res)
            res.append(root)
            if root.right:
                order(root.right, res)
                    
        tree = order(pRootOfTree, res)
        
        if len(res) > 1:        
            for ti in range(len(res)-1):
                res[ti + 1].left = res[ti]
                res[ti].right = res[ti + 1]
        
        return res[0]

空间复杂度O(N):辅助数组占用额外空间。不符合题目要求
时间复杂度O(N):N表示二叉树结点数量,遍历二叉树O(N),遍历数组O(N)

解法2:边中序遍历,边生成双向链表,不保存遍历结果
在这里插入图片描述
时间复杂度,中序遍历一遍二叉树,每个节点都只被访问了一次,故时间复杂度为O(n),n为节点数量
空间复杂度,定义了两个辅助指针pre, ans,故为O(1)

class Solution:
    def Convert(self , p):
        self.pre=None  #pre含义同上述图片代码
        self.ans=None  #ans为双向链表表头
        self.inOrder(p) #中序遍历,线索化二叉树
        return self.ans #返回答案,,最左端的节点,为双向链表的表头
    def inOrder(self,p): #中序遍历
        if p==None: #如果是空树的情况
            return
        self.inOrder(p.left)#递归调用,左子树线索化
        if p.left==None:#同上述图片中的代码,前驱线索化
            if self.ans==None:#第一个找到的左子树为空的节点,为双向链表的表头
                self.ans=p#答案即中序遍历最左端的节点
            p.left=self.pre#前驱线索化
            if self.pre!=None:#如果前驱节点存在
                self.pre.right=p#因为链表是双向的,建立前驱节点的后继线索
        if self.pre!=None and self.pre.right==None:#同上述图片中的代码,后继线索化
            self.pre.right=p#建立前驱节点的后继线索
            p.left=self.pre#建立后继节点的前驱线索
        self.pre=p
        self.inOrder(p.right)#递归调用,右子树线索化
        

注:

  1. 在构建双向链表时,每个节点肯定会出现p.left == None或if self.pre!=None and self.pre.right==None中的一种情况,所以用这两个条件。并在每个条件下,都构建节点的双向连接(即进行left=?和right=?操作)。
  2. 不必在意构建链表时会有节点没有指针指,地址丢失的情况。因为一直有指针p指向当前节点。

JZ79 判断是不是平衡二叉树
解法1:自顶向下

class Solution:
    def IsBalanced_Solution(self , pRoot: TreeNode) -> bool:
        # write code here
        if not pRoot:
            return True
        return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right) \
            and abs(self.depth(pRoot.left) - self.depth(pRoot.right)) <= 1
    def depth(self, root):
        if not root:
            return 0
        return max(self.depth(root.left), self.depth(root.right)) + 1

时间复杂度 O(Nlog2N):最差情况下,需要遍历树所有节点判断是否平衡,需要O(N)。判断每个节点最 大高度需要递归左右子树,需要占用 O(log2N),所以总共占用O(Nlog2N)
空间复杂度O(N):最差情况下(树退化为链表时),递归需要使用O(N) 的栈空间。(不李姐)

解法2:自底向上递归:

解法1在「计算二叉树高度」时遍历了树的结点,在「判断是否平衡」时又遍历了一次树的结点,因此产生了重复计算。针对解法一的优化是采用「自底向上」的解题思路:

从最底的叶子结点开始,计算该结点的高度。若该结点不平衡,则直接返回False,不用继续计算其他结点高度,否则返回其高度;
若自底向上的过程中一直都是平衡的,则最终的树是平衡的。
此方法每个结点(最坏时)仅会遍历一次,不会有重复计算。

class Solution:
    def IsBalanced_Solution(self , pRoot: TreeNode) -> bool:
        # write code here
        if not pRoot:
            return True
        if not self.IsBalanced_Solution(pRoot.left):
            return False
        if not self.IsBalanced_Solution(pRoot.right):
            return False
        if abs(self.depth(pRoot.left) - self.depth(pRoot.right)) > 1:
            return False
        return True
        
    def depth(self, root):
        if not root:
            return 0
        return max(self.depth(root.left), self.depth(root.right)) + 1

时间复杂度O(N):递归最差情况下(树退化为链表时),需要使用 O(N) 的栈空间。(不李姐)
空间复杂度O(N):递归需要使用额外的树节点数量的堆栈空间

JZ8 二叉树的下一个结点
Q1:首先问你一个问题,如果这道题出现在笔试题中,你会用什么方法做?如果出现在面试题中呢?
A1:我想你肯定有点疑惑,同一道题为什么还分出现在笔试题中还是面试题中呢?很显然,笔试题中只要能过就好,设计的算法丑点,慢点也无所畏,不一定需要最优解法,当然前提是能够通过。而面试中就不一样了,显然面试官希望听到最优解法。
A2,网友回答:我一开始也是想用方法二,但发现总是漏掉一些情况。所以说要是做笔试,最好就直接用方法一,递归遍历省时省力还不容易错。面试要是手撕这道,最好先跟hr说方法一,然后再表明:其实我还有一种更好的方法…之后再尝试写方法二

解法1:暴力解法

  • 根据给出的结点求出整棵树的根节点
  • 根据根节点递归求出树的中序遍历,存入vector
  • 在vector中查找当前结点,则当前结点的下一结点即为所求。

tyy看了题解后,自己写的,改了几个小bug后成功通过!和答案写法一样

class Solution:
    def GetNext(self, pNode):
        # write code here
        now = pNode
        while pNode.next:
            pNode = pNode.next
        vector = []  
        self.vec(pNode, vector)
        now_locat = vector.index(now)
        if now_locat < len(vector) - 1:
            return vector[now_locat + 1]
        return
    def vec(self, root, l):
        if root.left:
            self.vec(root.left, l)
        l.append(root)
        if root.right:
            self.vec(root.right, l)
  • 时间复杂度:第一步:最坏为O(N), N为整棵树结点的个数。第二步:O(N), 第三步:最坏为O(N), 所以整的时间复杂度:3*O(N)
  • 空间复杂度:O(N)

解法2:最优解法

分两种情况:
1、如果目标结点不是叶子结点
则在中序遍历中,下一个结点为当前结点的右子树的最左叶子结点
循环遍历,找到当前子树的最左叶子结点
2、如果目标结点是叶子结点而不是根节点,则需要向上寻找父节点
结点是父节点的左子结点,则在中序遍历中,目标结点的下一个结点就是父节点
结点是是父节点的右子结点,则在中序遍历中,还要继续寻找, 直到满足当前结点是父节点的左子结点

先看tyy的错误解法(运行超时):

class Solution:
    def GetNext(self, pNode):
        # write code here
        if pNode.right: # 如果有右孩子
            right = pNode.right
            while right:
                if right.left:
                    right = right.left
                if not right.left:
                    return right
        else: # 没有右孩子
            pre = pNode.next
            if pre:
                if pNode == pre.left: # 如果是左孩子,则返回父节点
                    return pre
                # 下面错了。因为只要是没有右孩子就一直往上寻找左孩子的父节点,if和else可以合并成一种情况
                else: # 如果是右孩子,则返回回溯左节点的父节点
                    while pre:
                        if pre.next.left:
                            if pre.next.left == pre:
                                return pre.next
                            else:
                                pre = pre.next

        return

正确解法:

class Solution:
    def GetNext(self, pNode):
        # write code here
        if pNode.right: # 如果有右孩子
            right = pNode.right
            while right:
                if right.left:
                    right = right.left
                if not right.left:
                    return right
        else: # 如果没有右孩子
            while pNode.next:
                pre = pNode.next
                if pNode == pre.left:
                    return pre
                pNode = pre
        return

时间复杂度 O(N):最坏的情况是遍历所有结点
空间复杂度 O(1):没有用到类似数组的类型数据

JZ28 对称的二叉树
解法1:迭代
tyy的解法:

class Solution:
    def isSymmetrical(self , pRoot: TreeNode) -> bool:
        # write code here
        if not pRoot:
            return True
        
        l_list = []
        r_list = []
        l_list.append(pRoot)
        r_list.append(pRoot)
        
        while l_list:
            now_l = l_list.pop(0)
            now_r = r_list.pop(0)

            if now_l.left:
                if not now_r.right:
                    return False
                else:
                    if now_l.left.val != now_r.right.val: # 注意是判断val相等而不是判断节点相等(不是if now_l.left != now_r.right)
                        return False
                l_list.append(now_l.left)
                r_list.append(now_r.right)
            if now_l.right:
                if not now_r.left:
                    return False
                else:
                    if now_l.right.val != now_r.left.val:
                        return False
                l_list.append(now_l.right)
                r_list.append(now_r.left)
                    
        return True

解法2:递归

class Solution:
    def isSymmetrical(self , pRoot: TreeNode) -> bool:
        # write code here
        if not pRoot:
            return True
        
        
        def same(root1, root2):
            if not root1 and not root2:
                return True
            if not root1 or not root2:
                return False
            if root1.val != root2.val:
                return False
            return same(root1.left, root2.right) and same(root1.right, root2.left)
        
        return same(pRoot.left, pRoot.right) 

JZ78 把二叉树打印成多行
解法 1:迭代(BFS,广度优先遍历)

class Solution:
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        # write code here
        result = []
        
        if not pRoot:
            return result
        
        l = []
        l.append(pRoot)
        
        while l:
            size = len(l)
            num = []
            for i in range(size): # 这句机智的代码我没想出来
                now = l.pop(0)
                num.append(now.val)
                if now.left:
                    l.append(now.left)
                if now.right:
                    l.append(now.right)
            result.append(num)
                    
        return result
        

时间复杂度:O(N) 空间复杂度:O(N)

解法2:递归
其实我们层序遍历一般不会用递归实现,但是这道题比较特殊,特殊之处在于,保存层数的 deep 可以索引出对应的层信息,方便结点直接找到同一层其他结点
我们考虑的问题就变成如何让同一层结点从左到右依次打印,第一个要点肯定是保证入队的顺序,先左子树,后右子树,再一个要点是需要保证建立 list 的顺序,即上一层的 list 先建立先存储进 lists,综合考虑,选用前序遍历的模板

class Solution:
    # 返回二维列表[[1,2],[4,5]]
    def Print(self, pRoot):
        # write code here
        result = []
        def align(root, depth):
            if root:
                if len(result)<depth:
                    result.append([])
                result[depth-1].append(root.val)
                align(root.left, depth + 1)
                align(root.right, depth + 1)
        align(pRoot,1)
        return result

时间复杂度:O(n)
空间复杂度:O(n)

JZ37 序列化二叉树
0. 再再重复一遍None和空字符串/列表/…的区别:添加链接描述
0.1:类型不同:type(None)类型为 <class ‘NoneType’>, type(‘’)为<class '‘str’>
0.2:判断的时候均为false:所以not ~为True

解法1:前序遍历
思路(官方题解法):利用二叉树递归,序列化即将二叉树的节点值取出,放入一个字符串中,我们可以按照前序遍历的思路,遍历二叉树每个节点,并将节点值存储在字符串中,我们用‘#’表示空节点,用‘!'表示节点与节点之间的分割。

反序列化即根据给定的字符串,将二叉树重建,因为字符串中的顺序是前序遍历,因此我们重建的时候也是前序遍历,即可还原。
在这里插入图片描述

import sys
#设置递归深度
sys.setrecursionlimit(100000) 
class Solution:
    def __init__(self):
        self.index = 0 
        self.s = ""

    #处理序列化(递归)
    def SerializeFunction(self, root):
        #空节点
        if not root:
            self.s += '#'
            return
        #根节点
        self.s += (str)(root.val) + '!'
        #左子树
        self.SerializeFunction(root.left) 
        #右子树
        self.SerializeFunction(root.right) 
    
    def Serialize(self, root): 
        if not root:
            return '#'
        self.s = ""
        self.SerializeFunction(root)
        return self.s
    
    #处理反序列化的功能函数(递归)
    def DeserializeFunction(self, s: str):
        # 到达叶节点时,构建完毕,返回继续构建父节点
        #空节点
        if s[self.index] == "#": 
            self.index += 1
            return None
        # 数字转换
        val = 0 (因为数字都是以字符串的形式存储的,如23:需要先算出十位的2,然后用2*10+3#遇到分隔符或者结尾
        while s[self.index] != '!':
            val = val * 10 + (int)(s[self.index])
            self.index += 1
        root = TreeNode(val)
        #序列到底了,构建完成
        self.index += 1
        #反序列化与序列化一致,都是前序
        root.left = self.DeserializeFunction(s)  
        root.right = self.DeserializeFunction(s)
        return root

    def Deserialize(self, s):
        if s == "#":
            return None
        return self.DeserializeFunction(s)

看看tyy默写的:

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def __init__(self) -> None:
        self.index = 0
        self.s = ""
    def SerializeFunction(self, root):
        if not root:
            self.s += "#"
            # return ""
            return # 第二处修改,可以省略""

        if root:
            self.s += str(root.val)
            self.s += "!"
        # self.s += self.SerializeFunction(root.left)
        # self.s += self.SerializeFunction(root.right)
        self.SerializeFunction(root.left)
        self.SerializeFunction(root.right) # 第三处修改,因为if root 为True时,self.SerializeFunction(root.left)没有返回值,所以不必写成self.s +=
    def Serialize(self, root):
        if not root:
            return "#" # 第一处修改,空树直接返回"#"
            # return 
        self.SerializeFunction(root)
        # write code here
        return self.s
        
    def DeserailizeFuction(self, s):
        val = 0
        while (s[self.index] != "#" and s[self.index] != "!"):
            val = val * 10 + int(s[self.index])
            self.index += 1
        # self.index += 1 # 第4处修改,因为需要先索引s[self.index],所以不能先将self.index += 1,应该索引完了再加
        # if s[self.index] == "#":
        #     return 
        if s[self.index] == "#":
            self.index += 1
            return 
        node = TreeNode(val)
        self.index += 1
        node.left = self.DeserailizeFuction(s)
        node.right = self.DeserailizeFuction(s)
        return node

    def Deserialize(self, s):
        if s == "#":
            return 
        return self.DeserailizeFuction(s)


        

解法1.1:一种较简单的前序遍历

class Solution:
    def __init__(self) -> None:
        self.s = []
        self.index = 0
    def Serialize(self, root):
        # write code here
        if not root:
            self.s.append("#")
            return 
        self.s.append(root.val)
        self.Serialize(root.left)
        self.Serialize(root.right)
        return self.s
    def Deserialize(self, s):
        # write code here
        if not s: # 不知道为啥,不加这个判断会报错,改成if s == ["#"]判断也报同样的错。明明def Serialize规定了空树返回["#"]
            return 
        if s[self.index] == "#" :
            self.index += 1
            return
        node = TreeNode(s[self.index])
        self.index += 1
        node.left = self.Deserialize(s)
        node.right = self.Deserialize(s)
        return node

解法2:层次遍历BFS

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Serialize(self, root): # 把树的值按顺序保存为str
        if not root:
            return 
        nodeset = []
        res = []
        nodeset.append(root)
        while nodeset:
            now = nodeset.pop(0) # pop() 用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
            if now == '#': # 修改3,因为下面的代码在遇到空节点时还会往res中添加'#',所以在这里需要判断是不是空节点
                res.append('#')
                continue
            res.append(str(now.val)) # 修改1,忘了添加now的值到res中
            if now.left:
                nodeset.append(now.left)
                # res.append(str(now.left.val)) # 修改2,不应该在这里就把left和right的值加到res中。应该是当把这儿元素pop出来的时候再往res中添加它的val
            else:
                nodeset.append("#") # 修改6,注意是往nodeset中添加节点,不要把nodeset写成res
            if now.right:
                nodeset.append(now.right)
                # res.append(str(now.right.val))
            else:
                nodeset.append("#")
        for i in range(len(res)-1, -1, -1):
            if res[i] != "#":
                break
        yes = ",".join(res[:i+1]) # list[索引]:返回还是list
        return yes 

        # write code here
    def Deserialize(self, s):
        if not s:
            return
        strin = s.split(",") # split: 返回列表
        nodeset = []
        now = strin.pop(0)
        root = TreeNode(int(now))
        nodeset.append(root)
        while strin:
            now = strin.pop(0) # 存节点值
            nownode = nodeset.pop(0) # 存节点
            if now != "#":
                nownode.left = TreeNode(int(now))
                nodeset.append(nownode.left) # 修改4,忘了将left节点加入到nodeset中
            if strin: # 修改5,先判断strin中是否还有元素值
                now = strin.pop(0)
                if now != "#":
                    nownode.right = TreeNode(int(now))
                    nodeset.append(nownode.right)
        return root
        # write code here

JZ84 二叉树中和为某一值的路径(三)
解法1: 两次遍历
先看看tyy只看了解题思路但没看代码之后自己写的代码:

class Solution:
    def __init__(self) -> None:
        self.num = 0
    def dfs(self, root, sum):
        if not root:
            return
        while sum: # 错误1:if 0为False,if not 0为True,而sum和节点的值均可以为0,所以这个循环条件使用错误;另外,如果在while循环下有一个条件不满足任何while下的if判断,while还是会继续执行,因为只要while的条件为True就会一直循环,和下面的判断条件没关系:[添加链接描述](https://pythontechworld.com/article/detail/o1CrVOKm3yNI)
            now_sum = sum-root.val
            if now_sum == 0:
                self.num += 1
                return
            else: # 错误2,当已经找到和为0的路径之后还可以继续往下寻找sum为0的路径
                sum = now_sum 
                self.dfs(root.left, sum)
                self.dfs(root.right, sum)

    def FindPath(self , root: TreeNode, sum: int) -> int:
        # write code here
        if not root:
            return 0
        self.dfs(root, sum)
        self.FindPath(root.left, sum)
        self.FindPath(root.right, sum)
        return self.num

所以正确解法应为:

class Solution:
    def __init__(self) -> None:
        self.num = 0
    def dfs(self, root, sum):
        if not root:
            return
        now_sum = sum-root.val
        if now_sum == 0:
            self.num += 1
        
        self.dfs(root.left, now_sum)
        self.dfs(root.right, now_sum)

    def FindPath(self , root: TreeNode, sum: int) -> int:
        # write code here
        if not root:
            return 0
        self.dfs(root, sum)
        self.FindPath(root.left, sum)
        self.FindPath(root.right, sum)
        return self.num
        

时间复杂度:O(n^2),其中n为二叉树的结点数,两层dfs嵌套递归
空间复杂度:O(n),每层dfs最深递归栈都只有n

解法2: 1次遍历+哈希表
哈希表中存放到从根节点到该节点的路径和,以及路径和的出现次数。如果路径和减sum存在于哈希表中,说明路径的后半段的路径和为sum。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

看看tyy看了解题思路之后默写的:

class Solution:
    def __init__(self) -> None:
        self.d = {}
        self.d[0] = 1
        self.res = 0
    def little(self, root, sum, all):
        if not root:
            return
        all += root.val # 先统计从根节点到当前节点的路径和
        if all - sum in self.d.keys(): # 修改1,应该先判断有无路径,再像哈希表中添加元素
            self.res += self.d[all-sum]
        if all not in self.d.keys():
            self.d[all] = 1
        else:
            self.d[all] += 1
        # if all - sum in self.d.keys():
        #    self.res += self.d[all-sum]
        self.little(root.left, sum, all)
        self.little(root.right, sum, all)

        return self.res
        
    def FindPath(self, root: TreeNode, sum: int) -> int:
        # write code here
        if not root:
            return self.res
        return self.little(root, sum, 0)

时间复杂度:O(n),其中n为二叉树的结点数,遍历一次二叉树,哈希表的操作都是O(1)
空间复杂度:O(n),哈希表大小及递归栈最大为n

JZ86 在二叉树中找到两个节点的最近公共祖先
方法1:路径比较法(深度优先搜索,dfs),官方给出的解法1,具体思路可查看官方解答

step 1:利用dfs求得根节点到两个目标节点的路径:每次选择二叉树的一棵子树往下找,同时路径数组增加这个遍历的节点值。
step 2:一旦遍历到了叶子节点也没有,则回溯到父节点,寻找其他路径,回溯时要去掉数组中刚刚加入的元素。
step 3:然后遍历两条路径数组,依次比较元素值。
step 4:找到两条路径第一个不相同的节点即是最近公共祖先。
在这里插入图片描述
这是tyy看了官方解答之后自己写的,修改几次之后终于提交通过:

class Solution:
    def __init__(self) -> None:
        self.flag = False
     
    def findRoad(self, root, t, o): # t为可变参数,所有每一次递归其值会改变:https://blog.csdn.net/weixin_40875443/article/details/123648262
        t.append(root.val) # 修改1:要将节点的值加入
         
        if root.val == o:
            self.flag = True
            # return  # 修改3,如果输入的是根节点,而没有return t,则lowestCommonAncestor函数中的t1没有返回值,就错了呗
            return t

        if self.flag == False and root.left:
            self.findRoad(root.left, t, o)
            if self.flag == True:
                return t
        if self.flag == False and root.right:
            self.findRoad(root.right, t, o)
            if self.flag == True:
                return t
 
        t.pop() # 其实t.pop()是有返回值的,不过这样写也是正确的
        return
 
    def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
        # write code here
        t1, t2 = [], []
        t1 = self.findRoad(root, t1, o1)
        # print('t1')
        # for j in t1:
        #     print(j.val)
         
        self.flag = False
        t2 = self.findRoad(root, t2, o2)
        # print('t2')
        # for j in t2:
        #     print(j.val)
        res = None
        i = 0
 
        while i <len(t1) and i < len(t2):
            if t1[i] == t2[i]:
                res = t1[i]
                # print(res.val)
                i += 1
            else:
                break
        # print('res:', res.val)
        return res

时间复杂度:O(n),其中n为二叉树节点数,递归遍历二叉树每一个节点求路径,后续又遍历路径
空间复杂度:O(n),最坏情况二叉树化为链表,深度为n,递归栈深度和路径数组为n

解法2:二叉树递归

参考官方第二种解法的解答,说实话,没大看懂

class Solution:
    def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
        # write code here
        if not root: # 修改1:注意,和下一个if判断条件的顺序不能颠倒,否则会出错
            return -1
        if root.val == o1 or root.val == o2:
            return root.val

        left = self.lowestCommonAncestor(root.left, o1, o2) # 修改2,注意参数的个数,应该输入3个参数,不要写错
        right = self.lowestCommonAncestor(root.right, o1, o2)

        if left == -1:
            return right
        if right == -1:
            return left
        
        return root.val

时间复杂度:O(n),其中n为节点数,递归遍历二叉树每一个节点
空间复杂度:O(n),最坏情况二叉树化为链表,递归栈深度为n

JZ68 二叉搜索树的最近公共祖先

解法1:二叉树递归
利用左子树比根节点的值小,右子树比根节点的值大的性质,tyy自己想的(思路错了,但是代码有小错误,看了答案之后改对了)

class Solution:
    def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
        # write code here
        if not root:
            return -1
        if (p <= root.val <= q) or (q <= root.val <= p): # 修改1,注意在所有判断条件中不要忘了等于号
            return root.val
        elif (p <= root.val) and (q <= root.val):
            return self.lowestCommonAncestor(root.left, p, q)
        elif (p >= root.val) and (q >= root.val):
            return self.lowestCommonAncestor(root.right, p, q)
       

注:用JZ86的解法2的代码也能通过

解法2:搜索路径比较
分别找出两个节点的搜索路径,然后依次比较

tyy看了官方思路之后自己写的代码:

class Solution:
    def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
        # write code here
        node1 = root
        path1 = []
        while node1:
            path1.append(node1.val)
            if p == node1.val:
                break
            elif p < node1.val:
                node1 = node1.left
                continue
            elif p > node1.val:
                node1 = node1.right
                continue

        node2 = root # 注:其实可以把这两处代码写成一个函数,分别对p和q调用
        path2 = []
        while node2:
            path2.append(node2.val) 
            if q == node2.val: # 修改1,不要把q写成p
                break
            elif q < node2.val:
                node2 = node2.left # 修改2,不要把node2写成root
                continue
            elif q > node2.val:
                node2 = node2.right
                continue

        i = 0
        while i < len(path1) and i < len(path2):
            if path1[i] == path2[i]:
                i += 1
            else:
                break
        return path1[i-1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值