leetcode (Tree easy)

leetcode Tree easy

# leetcode Tree easy problem
class TreeNode(object):
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right = None

class Solution(object):
    # 1,leetcode100 相同的树,给定两个个二叉树,编写一个函数判断两个二叉树是否相同
    def isSameTree(self,p,q):
        """
        :type p : TreeNode
        :type q : treeNode
        :rtype : bool
        """
        # 前三个if语句均属于递归出口
        # 如果二者都为空,则返回True
        if not p and not q:
            return True
        # 如果二者有一个为空,另外一个不为空,则返回false
        # 这个地方需要注意
        """
        [p , q , not p or not q]
        [1 , 1 , 0]
        [1 , 0 , 1]
        [0 , 1 , 1]
        [0 , 0 , 1]
        """
        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)
    # 1,leetcode100 相同的树,采用非递归的方法写出来
    # 将递归形式转换成为非递归形式的主要思想方法是借助于栈,将p,q作为一个元组同时压入到栈中,省去了上面的三个if语句
    def isSameTree_2(self,p,q):
        """
        :type p : TreeNode
        :type q : TreeNode
        :rtype : bool
        """
        # 创建一个栈
        stack = []
        # 首先将p,q等根节点压入到栈中
        stack.append((p,q))
        # 循环操作,这里面包括了二者有一个为空另外一个不是空,或者二者都为空的状况
        while(stack):
            a,b = stack.pop()
            # 若树节点不存在则跳过该次循环
            if not a and not b:
                continue
            # 同样,若想把左右子树节点压入到栈中,也必须首先保证其节点存在
            if a and b and a.val == b.val:
                # 将两个树的左子树节点压入到栈中
                stack.append((a.left,b.left))
                # 将两棵树的右子树节点压入到栈中
                stack.append((a.right,b.right))
            else:
                return False
        # 全部循环完,没有不想等的两个节点,则返回True
        return True
    # leetcode 101 对称二叉树,给定一个二叉树,判断其是否为对称二叉树
    # 思想,采用递归操作,递归判断其左子树与其右子树是否为对称二叉树
    def isSymmetric(self,root):
        """
        :type root : TreeNode
        :rtype : bool
        """
        # 辅助函数,将一个树的跟节点当作是两棵树传入
        def isMirror(p,q):
            # 如果节点均为空
            if not p and not q:
                return True
            # 一个树节点为空,另外一个不是空
            if not p or not q:
                return False
            # 均不是空,但是需要判断其数值是否相同
            if p.val != q.val:
                return False
            # 递归操作
            return isMirror(p.left,q.right) and isMirror(p.right,q.left)
        return isMirror(root,root)
    # 讲道理,能用递归的肯定就能转换成为非递归操作,这里我们将递归操作使用栈转换成为非递归操作
    def isSymmetric_2(self,root):
        """
        :type root : TreeNode
        :rtype : bool
        """
        # 创建一个递归栈
        stack = []
        # 首先将一棵树作为两棵压入到栈中
        stack.append((root,root))
        while stack:
            # 弹出来
            a,b = stack.pop()
            # 如果二者树节点都不存在
            if not a and not b:
                continue
            # 两个树节点都存在,并且二者的val值相等
            if a and b and a.val == b.val:
                # 压入新的节点
                stack.append((a.left,b.right))
                stack.append((a.right,b.left))
            # 其他情况,一者树节点不存在,或者是两个树节点都存在,但是树节点的val值不想等
            else:
                return False
        # 全部判断完成,返回True
        return True
    # leetcode 104 二叉树的最大深
    # 给定一个二叉树,返回该二叉树的最大深度
    # 同样,我们还是首先采用递归来写
    def maxDepth(self,root):
        """
        :type root:TreeNode
        :rtype : int
        """
        # 递归出口,如果root不存在,返回0
        if not root:
            return 0
        # root存在,采用递归操作
        # 结果就是返回,左右子树较大的那个
        return max(self.maxDepth(root.left),self.maxDepth(root.right))+1
    # 然后,我们采用非递归操作进行这道算法题
    def maxDepth_2(self,root):
        """
        :type root:TreeNode
        :rtype : int
        """
        # 首先,创建一个递归栈
        stack = []
        depth = 0
        if not root:
            return 0
        # (depth,TreeNode)
        stack.append((1,root))
        while stack:
            temp_depth , p = stack.pop()
            # 存在该树节点
            if p is not None:
                # 更新depth
                depth = max(temp_depth,depth)
                # 往栈中添加元素
                stack.append((temp_depth,p.left))
                stack.append((temp_depth,p.right))
        return depth
    
    # leetcode 107 二叉树的层次遍历2
    # 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
    def levelOrderBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        # 思想,层次遍历类似于BFS,借助于队列
        # 首先创建一个队列
        queue = []
        res = []
        if not root:
            return []
        queue.append(root)
        while queue:
            n = len(queue)
            temp = []
            for i in range(n):
                a = queue.pop(0)
                temp.append(a.val)
                if a.left:
                    queue.append(a.left)
                if a.right:
                    queue.append(a.right)
            res.append(temp)
                
        return res[::-1]
    # leetcode 108. 将有序数组转换为二叉搜索树
    # 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
    # 思想:二分法
    def sortedArrayToBST(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        # 如果nums没有元素,则是空树
        if not nums:
            return None
        start = 0
        end = len(nums)-1
        mid = (start + end)//2
        if start > end:
            return None
        root = TreeNode(nums[mid])
        root.left = self.sortedArrayToBST(nums[:mid])
        root.right = self.sortedArrayToBST(nums[mid+1:])
        return root
    # leetcode 110
    # 给定一个二叉树,判断它是否是高度平衡的二叉树。
    # 思想:采用递归判断其左右子树是否为平衡二叉树,是否为平衡二叉树的标准是左右子树的高也就是深度的差的绝对值小于等于1
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def depth(root):
            if not root:
                return 0
            return max(depth(root.left),depth(root.right))+1
        if not root:
            return True
        return abs(depth(root.left) - depth(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
    # leetcode 111
    # 给定一个二叉树,找出其最小深度。
    # 思想:采用层次遍历,第一次出现没有左右子树的就是最小深度
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        else:
            stack, min_depth = [(1, root),], float('inf')
        
        while stack:
            depth, root = stack.pop()
            children = [root.left, root.right]
            if not any(children):
                min_depth = min(depth, min_depth)
            for c in children:
                if c:
                    stack.append((depth + 1, c))
        
        return min_depth
    # leetcode 112 路径总和
    # 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
    # 思想dfs
    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)
        """
        if not root:
            return False

        de = [(root, sum - root.val), ]
        while de:
            node, curr_sum = de.pop()
            if not node.left and not node.right and curr_sum == 0:  
                return True
            if node.right:
                de.append((node.right, curr_sum - node.right.val))
            if node.left:
                de.append((node.left, curr_sum - node.left.val))
        return False
    # leetcode 226 反转二叉树
    # 反转一棵二叉树
    # 思想:递归
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root is None:
            return
        root.left, root.right = self.invertTree(root.right),self.invertTree(root.left)
        return root
    # leetcode 235. 二叉搜索树的最近公共祖先
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if root.val > p.val and root.val > q.val:
            return self.lowestCommonAncestor(root.left,p,q)
        elif root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right,p,q)
        else:
            return root
    # leetcode 257. 二叉树的所有路径
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        """
        def construct_paths(root, path):
            if root:
                path += str(root.val)
                if not root.left and not root.right:  # 当前节点是叶子节点
                    paths.append(path)  # 把路径加入到答案中
                else:
                    path += '->'  # 当前节点不是叶子节点,继续递归遍历
                    construct_paths(root.left, path)
                    construct_paths(root.right, path)

        paths = []
        construct_paths(root, '')
        return paths
        """
        if not root:
            return []
        
        paths = []
        stack = [(root, str(root.val))]
        while stack:
            node, path = stack.pop()
            if not node.left and not node.right:
                paths.append(path)
            if node.left:
                stack.append((node.left, path + '->' + str(node.left.val)))
            if node.right:
                stack.append((node.right, path + '->' + str(node.right.val)))
        
        return paths
    # 404. 左叶子之和
    # 计算给定二叉树的所有左叶子之和。
    def sumOfLeftLeaves(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        if root and root.left and not root.left.left and not root.left.right:
            return root.left.val+self.sumOfLeftLeaves(root.right)
        return self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
    # leetcode 437. 路径总和 III
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int
        """
        if not root:
            return 0
        def dfs(root,sum):
            count=0  #记录路径个数
            if not root:
                return 0
            if root.val==sum:
                count+=1
            count+=dfs(root.left,sum-root.val)
            count+=dfs(root.right,sum-root.val)
            return count
        return dfs(root,sum)+self.pathSum(root.left,sum)+self.pathSum(root.right,sum)
    # 501. 二叉搜索树中的众数
     def findMode(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        def inorder(root,res = []):
            if not root:
                return 
            inorder(root.left,res)
            res.append(root.val)
            inorder(root.right,res)
            return res

        if not root:
            return 
        temp = inorder(root)
        dic = {}
        res = []
        for index,num in enumerate(temp):
            if num not in dic:
                dic[num] = 1
            else:
                dic[num] +=1
        n = max(dic.values())
        for index,num in dic.items():
            if dic[index] == n:
                res.append(index)
        return res
    #leetcode 530. 二叉搜索树的最小绝对差
    def getMinimumDifference(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 目标就是找到最小的元素与第二小的元素,二者做差即可,中序遍历(错)
        # 注意题目中给的是差的绝对值的最小
        def inorder(root,res = []):
            if not root:
                return 
            inorder(root.left)
            res.append(root.val)
            inorder(root.right)
            return res
        if not root:
            return 
        temp = inorder(root)
        temp_2 =[]
        for i in range(1,len(temp)):
            temp_2.append(abs(temp[i]-temp[i-1]))

        return min(temp_2)
    
# leetcode 538  把二叉搜索树转换为累加树    
class Solution(object):
    """
    在递归方法中,我们维护一些递归调用过程中可以访问和修改的全局变量。
    首先我们判断当前访问的节点是否存在,如果存在就递归右子树,递归回来的时候更新总和和当前点的值,然后递归左子树。
    如果我们分别正确地递归 root.right 和 root.left ,那么我们就能正确地用大于某个节点的值去更新此节点,然后才遍历比它小的值。
    """
    def __init__(self):
        self.total = 0

    def convertBST(self, root):
        if root is not None:
            self.convertBST(root.right)
            self.total += root.val
            root.val = self.total
            self.convertBST(root.left)
        return root
    """
    一个描述迭代栈的方法就是通过递归的思想。
    首先我们初始化一个空的栈并把根节点作为当前节点。
    然后只要在栈中有未遍历节点或者 node 节点不为空,我们就将当前节点到最右边叶子路径上的点全部压入栈中。
    这与递归过程中我们总是先走右子树的思路是一致的,这个思路确保我们总是降序遍历所有节点的值。
    接下来,我们访问栈顶节点,并考虑它的左子树,这就像我们递归中先遍历当前节点再遍历它的左子树的思路。
    最后,我们的栈为空并且 node 指向树中最小节点的左孩子 null ,循环结束。

    """
    def convertBST(self, root):
        total = 0
        
        node = root
        stack = []
        while stack or node is not None:
            # push all nodes up to (and including) this subtree's maximum on
            # the stack.
            while node is not None:
                stack.append(node)
                node = node.right

            node = stack.pop()
            total += node.val
            node.val = total

            # all nodes with values between the current and its parent lie in
            # the left subtree.
            node = node.left

        return root
    
    #leetcode 543. 二叉树的直径
    # 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。
    def diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.ans = 1
        def depth(node):
            if not node: return 0
            L = depth(node.left)
            R = depth(node.right)
            self.ans = max(self.ans, L+R+1)
            return max(L, R) + 1

        depth(root)
        return self.ans - 1
#leetcode 559. N叉树的最大深度
"""
# Definition for a Node.
class Node(object):
    def __init__(self, val, children):
        self.val = val
        self.children = children
"""
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        """
        if root is None: 
            return 0 
        elif root.children == []:
            return 1
        else: 
            height = [self.maxDepth(c) for c in root.children]
            return max(height) + 1 
        """
        stack = []
        if root is not None:
            stack.append((1, root))
        
        depth = 0
        while stack != []:
            current_depth, root = stack.pop()
            if root is not None:
                depth = max(depth, current_depth)
                for c in root.children:
                    stack.append((current_depth + 1, c))
                
        return depth
     # leetcode 589. N叉树的前序遍历
    def preorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        if root is None:
            return []
        
        stack, output = [root], []            
        while stack:
            root = stack.pop()
            output.append(root.val)
            stack.extend(root.children[::-1])
                
        return output
    

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
# leetcode 572. 另一个树的子树
class Solution(object):
    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """
        def issame(p, q):
            if not p and not q:
                return True
            if not p or not q:
                return False
            return p.val == q.val and issame(p.left, q.left) and issame(p.right, q.right)


        if not t:
            return True
        if not s:
            return False
        return issame(s, t) or self.isSubtree(s.left, t) or self.isSubtree(s.right, t)
    # leetcode1022. 从根到叶的二进制数之和
    def sumRootToLeaf(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        def dfs(node, sum):
            if node:
                sum = sum*2 + node.val
                if not node.left and not node.right:
                    return sum
                return dfs(node.left, sum) + dfs(node.right, sum)
            else:
                return 0


        return dfs(root, 0)
    # leetcode 993. 二叉树的堂兄弟节点
    def isCousins(self, root, x, y):
        """
        :type root: TreeNode
        :type x: int
        :type y: int
        :rtype: bool
        """
        parent = {}
        depth = {}
        def dfs(node, par = None):
            if node:
                depth[node.val] = 1 + depth[par.val] if par else 0
                parent[node.val] = par
                dfs(node.left, node)
                dfs(node.right, node)

        dfs(root)
        return depth[x] == depth[y] and parent[x] != parent[y]
    # leetcode65. 单值二叉树
    def isUnivalTree(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        vals = []

        def dfs(node):
            if node:
                vals.append(node.val)
                dfs(node.left)
                dfs(node.right)

        dfs(root)
        return len(set(vals)) == 1
    # leetcode 938. 二叉搜索树的范围和
    def rangeSumBST(self, root, L, R):
        """
        :type root: TreeNode
        :type L: int
        :type R: int
        :rtype: int
        """
        def dfs(node):
            if node:
                if L <= node.val <= R:
                    self.ans += node.val
                if L < node.val:
                    dfs(node.left)
                if node.val < R:
                    dfs(node.right)

        self.ans = 0
        dfs(root)
        return self.ans
    # leetcode 897. 递增顺序查找树
    def increasingBST(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        def inorder(node):
            if node:
                inorder(node.left)
                node.left = None
                self.cur.right = node
                self.cur = node
                inorder(node.right)

        ans = self.cur = TreeNode(None)
        inorder(root)
        return ans.right
    
     
   
    
    
    
    
        
if __name__ == '__main__':
    pass
                
    
        
        
        
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值