Leetcode刷题之二叉树篇(四)

二叉树篇

98. 验证二叉搜索树

  • 思路1:对二叉树进行中序遍历,如果是二叉树搜索树 自然遍历序列是升序的。因此采取数组保存中序遍历结果,如果前一个元素大于等于后面一个元素 则返回False

    思路2:对二叉树进行中序遍历,如果是二叉树搜索树 自然遍历序列是升序的。采取一个成员变量preVal遍历记录上一次中序遍历的结果,然后与当前值比较即可

# 思路1
class Solution(object):
    def __init__(self):
        self.nums = []

    def isValidBST(self, root):
        self.dfs(root)
        for i in range(len(self.nums)-1):
            if self.nums[i]>=self.nums[i+1]:
                return False
        return True

    def dfs(self,root): 
        if not root: return
        self.dfs(root.left)
        self.nums.append(root.val)
        self.dfs(root.right)
# 思路2
class Solution(object):
    def __init__(self):
        self.preVal = -pow(2,31)-1

    def isValidBST(self, root):
        return self.dfs(root)

    def dfs(self,root):
        if not root: return True
        a = self.dfs(root.left)
        if self.preVal>=root.val:
            return False
        self.preVal = root.val
        b = self.dfs(root.right)
        return a and b

总结:中序遍历的递归写法 可更改成 借助显示栈的迭代写法!

36. 二叉搜索树与双向链表

  • 思路1:引入哨兵节点,对二叉搜索树进行中序遍历,且用preNode记录中序遍历的上一个节点,然后preNode节点与当前节点相互连接即可
class Solution(object):
    def __init__(self):
        self.preNode = None

    def treeToDoublyList(self, root):
        if not root: return None
        auxi = TreeNode(0,None,root)
        self.preNode = auxi
        self.dfs(root)
        auxi.right.left = self.preNode
        self.preNode.right = auxi.right
        return auxi.right

    def dfs(self,root):
        if not root: return
        self.dfs(root.left)
        root.left = self.preNode
        self.preNode.right = root
        self.preNode = root  
        self.dfs(root.right)

68 - I. 二叉搜索树的最近公共祖先

  • 思路1:采取迭代的思路,由于是二叉搜索树,所以当前节点值同时大于p,q节点值 当前节点就更新到其左孩子,其他情况类似分析
class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        cur = root
        while cur:
            if cur.val > p.val and cur.val > q.val:
                cur = cur.left
            elif cur.val < p.val and cur.val < q.val:
                cur = cur.right
            else:
                return cur 

236. 二叉树的最近公共祖先

  • 思路1:通过后续遍历 找到后代节点后再去寻找祖先(如果root为p和q,root可能是祖先 当root左子树和右子树同时包含后代节点时 需要将结果更新为 当前root)
class Solution(object):
    def __init__(self):
        self.ret = TreeNode(0)

    def lowestCommonAncestor(self, root, p, q):
        self.dfs(root,p,q)
        return self.ret

    def dfs(self,root,p,q):
        # 只有先访问了 两个儿子节点   才能知道祖先是谁  所以需要后续遍历 
        if not root: 
            return False
        if root == p or root == q:
            self.ret = root
            return True
        a = self.dfs(root.left,p,q)
        b = self.dfs(root.right,p,q)
        if a and b:
            self.ret = root
        return a or b

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

  • 思路1:根据前序遍历的根节点位置,找到中序遍历对应的下标,即可将数组分成 左子树的先序遍历和中序遍历,右子树的先序遍历和中序遍历 递归构造即可
class Solution(object):
    def buildTree(self, preorder, inorder):
        root = self.dfs(preorder,inorder)
        return root

    def dfs(self,preorder,inorder):
        if not preorder: return None
        index = inorder.index(preorder[0])
        tmp = TreeNode(preorder[0])
        tmp.left = self.dfs(preorder[1:index+1],inorder[:index])
        tmp.right = self.dfs(preorder[index+1:],inorder[index+1:])
        return tmp

33. 二叉搜索树的后序遍历序列

  • 思路1:遇到二叉树+数组,基本都是递归+双指针的思想。后续遍历的最后一个节点是子树的根节点,二叉搜索树左子树值均小于根节点值,右子树值均大于根节点值,只需根据根节点找到右子树后续遍历起始节点,如果后面出现小于根节点的,即不为后续遍历序列
class Solution(object):
    def verifyPostorder(self, postorder):
        i,j = 0,len(postorder)-1
        return self.dfs(postorder,i,j)

    def dfs(self,postorder,i,j):
        if i>=j: return True
        mid = i
        while postorder[mid]<postorder[j]:
            mid += 1 
        cur = mid
        while cur<=j:
            if postorder[cur]<postorder[j]:
                 return False
            cur += 1
        a = self.dfs(postorder,i,mid-1) # 左子树
        b = self.dfs(postorder,mid,j-1) # 右子树
        return a and b

450. 删除二叉搜索树中的节点

  • 思路1:引入哨兵节点,因为可能删除根节点。去遍历二叉搜索,查找key的节点,过程中记录pre(前一个)和cur(当前)节点,然后根据不同情况,删除节点 对剩下节点合理连接,并保留二叉树的性质即可
class Solution(object):
    def deleteNode(self, root, key):
        if not root: return None
        auxi = TreeNode(0,root,None); # 哨兵节点
        pre,cur = auxi,root
        while True:
            if cur.val == key: break
            pre = cur
            if key < cur.val: cur = cur.left
            elif key > cur.val: cur = cur.right
            if not cur: break
        if not cur: return auxi.left # 找不到删除的节点
        if not cur.left: 
            if pre.left == cur: pre.left = cur.right
            if pre.right == cur: pre.right = cur.right
        elif not cur.right: 
            if pre.left == cur: pre.left = cur.left
            if pre.right == cur: pre.right = cur.left
        else: 
            tmp = cur.left
            while tmp.right:
                tmp = tmp.right
            tmp.right = cur.right
            if pre.left == cur: pre.left = cur.left
            if pre.right == cur: pre.right = cur.left
        return auxi.left
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值