Leetcode刷题之二叉树篇(三)

二叉树篇

404. 左叶子之和

  • 思路1:先找到二叉树中的叶子节点,然后对叶子节点的 左叶子求和。左叶子可以通过,该叶子节点是其父亲节点的左孩子确定。如果二叉树只有根节点这种特殊情况,左叶子和为0
class Solution(object):
    def __init__(self):
        self.sum = 0

    def sumOfLeftLeaves(self, root):
        if not root.left and not root.right: return 0
        self.dfs(root,None)
        return self.sum

    def dfs(self,root,father):
        if not root: return  # 终止条件
        if not root.left and not root.right: # 叶子节点
            if father.left == root: # 左叶子
                self.sum += root.val
        self.dfs(root.left,root)
        self.dfs(root.right,root)

总结:递归写法 1)先写终止条件 2)思考函数处理逻辑 3)递归调用函数自身

257. 二叉树的所有路径

  • 思路1:前序遍历二叉树的节点,记录路径字符串 当访问到叶子节点,将其添加到结果数组
class Solution(object):
    def __init__(self):
        self.ret = []

    def binaryTreePaths(self, root):
        self.dfs(root,'')
        return self.ret

    def dfs(self,root,path):
        if not root: return # 终止条件
        if not root.left and not root.right:
            self.ret.append(path+str(root.val))
        self.dfs(root.left,path+str(root.val)+'->')
        self.dfs(root.right,path+str(root.val)+'->')

112. 路径总和

  • 思路1:前序遍历二叉树的节点,记录路径当前和,访问到叶子节点,路径当前和如果等于target,则存在题目要求路径,返回True;否则返回Fasle。只要存在一个这样的路径即可,因此用 或运算(or)
class Solution(object):
    def hasPathSum(self, root, targetSum):
        return self.dfs(root,targetSum,0)

    def dfs(self,root,targetSum,curSum):
        if not root: return False # 终止条件
        if not root.left and not root.right:
            curSum += root.val # 加上叶节点val
            if curSum == targetSum:
                return True 
            else:
                return False
        a = self.dfs(root.left,targetSum,curSum+root.val)
        b = self.dfs(root.right,targetSum,curSum+root.val)
        return a or b

113. 路径总和II

  • 思路1:前序遍历二叉树的节点,记录路径当前和 以及路径节点,访问到叶子节点,路径当前和如果等于target,则添加路径。在记录路径过程中,采取回溯的思想
class Solution(object):
    def __init__(self):
        self.ret = []
        self.nums = []

    def pathSum(self, root, targetSum):
        self.dfs(root,targetSum,0) # 最开始curSum初始为0
        return self.ret

    def dfs(self,root,targetSum,curSum):
        if not root: return # 终止条件
        self.nums.append(root.val)
        if not root.left and not root.right:
            curSum += root.val # 加上叶节点val
            if curSum == targetSum:
                self.ret.append(self.nums[:])
            self.nums.pop(-1)
            return
        self.dfs(root.left,targetSum,curSum+root.val)
        self.dfs(root.right,targetSum,curSum+root.val)
        self.nums.pop(-1) # 回溯的思想

437. 路径总和III

  • 思路1:采取两层深度优先遍历,第一层遍历二叉树的每个节点,第二层以每个节点为 根节点,进行路径和求和操作,采取回溯的思想统计满足题意的路径计数
  • 思路2:我们利用先序遍历二叉树,记录下根节点 root 到当前节点cur路径上 除当前节点以外所有节点的前缀和,在已保存的路径前缀和中查找是否存在前缀和刚好等于当前节点到根节点的前缀和 cur 减去targetSum。
# 思路1
class Solution(object):
    def __init__(self):
        self.cnt = 0
        self.curSum = 0

    def pathSum(self, root, targetSum):
        self.preOrder(root,targetSum)
        return self.cnt

    def preOrder(self,root,targetSum):
        if not root: return 
        self.dfs(root,targetSum)
        self.preOrder(root.left,targetSum)
        self.preOrder(root.right,targetSum)

    def dfs(self,root,targetSum):
        if not root: return # 终止条件
        self.curSum += root.val
        if self.curSum == targetSum: # 计数加1
            self.cnt += 1
        self.dfs(root.left,targetSum)
        self.dfs(root.right,targetSum)
        self.curSum -= root.val # 回溯
# 思路2
class Solution:
    def __init__(self):
        self.prefix = collections.defaultdict(int)

    def pathSum(self, root, targetSum):
        self.prefix[0] = 1
        return self.dfs(root, 0,targetSum)

    def dfs(self,root, cur,targetSum):
        if not root:
            return 0
        cur += root.val
        ret = 0
        ret += self.prefix[cur - targetSum]
        self.prefix[cur] += 1
        ret += self.dfs(root.left, cur,targetSum)
        ret += self.dfs(root.right, cur,targetSum)
        self.prefix[cur] -= 1 # 回溯
        return ret

129. 求根节点到叶节点数字之和

  • 思路1:前序遍历二叉树的节点,记录路径字符串 当访问到叶子节点,将路径字符串转成int数字,并累加起来即可
class Solution(object):
    def __init__(self):
        self.ret = 0

    def sumNumbers(self, root):
        self.dfs(root,'')
        return self.ret

    def dfs(self,root,path):
        if not root: return # 终止条件
        if not root.left and not root.right:
            self.ret += int(path+str(root.val))
        self.dfs(root.left,path+str(root.val))
        self.dfs(root.right,path+str(root.val))

54. 二叉搜索树的第k大节点

  • 思路1:采取中序遍历的,但是采取降序的方式 即先访问右孩子,再访问中间节点,再访问左孩子当访问到第k个节点 结束dfs,并返回该节点
class Solution(object):
    def __init__(self):
        self.cnt = 0
        self.ret = 0

    def kthLargest(self, root, k):
        self.dfs(root,k)
        return self.ret
    
    def dfs(self,root,k):
        if not root: return 
        self.dfs(root.right,k)
        self.cnt += 1
        if self.cnt == k:
            self.ret = root.val
            return 
        self.dfs(root.left,k)

230. 二叉搜索树中第K小的元素

  • 思路1:采取中序遍历的,但是采取升序的方式 即先访问左孩子,再访问中间节点,再访问右孩子当访问到第k个节点 结束dfs,并返回该节点
class Solution(object):
    def __init__(self):
        self.cnt = 0
        self.ret = 0

    def kthSmallest(self, root, k):
        self.dfs(root,k)
        return self.ret
    
    def dfs(self,root,k):
        if not root: return 
        self.dfs(root.left,k)
        self.cnt += 1
        if self.cnt == k:
            self.ret = root.val
            return 
        self.dfs(root.right,k)

108. 将有序数组转换为二叉搜索树

  • 思路1:采取递归+双指针做法,递归过程中采取二分的思想 根据有序数组重构二叉树即可
class Solution(object):
    def sortedArrayToBST(self, nums):
        i,j = 0,len(nums)-1
        return self.dfs(nums,i,j)

    def dfs(self,nums,i,j):
        if i>j: return None
        mid = (i+j) // 2
        tmp = TreeNode(nums[mid])
        tmp.left = self.dfs(nums,i,mid-1)
        tmp.right = self.dfs(nums,mid+1,j)
        return tmp

总结:一般涉及到数组和二叉树的题目,都会采取dfs的做法 。而且一般是 递归+双指针

1038. 把二叉搜索树转换为累加树

思路1:先先序遍历 记录整棵树的累计和sum 再根据中序遍历记录访问到目前为止节点的累计和curSum,然后将当前节点值赋值成sum-curSum

class Solution(object):
    def __init__(self):
        self.curSum = 0
        self.sum = 0

    def bstToGst(self, root):
        self.preOrder(root)
        self.inOrder(root)
        return root

    def preOrder(self,root):
        if not root: return 
        self.sum += root.val
        self.preOrder(root.left)
        self.preOrder(root.right)

    def inOrder(self,root):
        if not root: return None
        self.inOrder(root.left)
        tmp = root.val
        root.val = self.sum - self.curSum
        self.curSum += tmp
        self.inOrder(root.right)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值