树面试题 python

递归

  1. 二叉树的最大深度
    思路:递归,没节点,返回0,有节点,返回1+max(l,r)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root):
        if not root:
            return 0
        return 1+max(self.maxDepth(root.left),self.maxDepth(root.right))
  1. 平衡二叉树
    思路:求最大深度,判断abs(左子节点最大深度-右子节点最大深度)<=1 and 左子节点是否是平衡的 and 右子节点是否是平衡的。
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        return abs(self.maxDepth(root.right)-self.maxDepth(root.left))<=1 and self.isBalanced(root.left) and self.isBalanced(root.right)
    def maxDepth(self, root):
        if not root:
            return 0
        return 1+max(self.maxDepth(root.right),self.maxDepth(root.left))
  1. 二叉树的直径(最长路径是边的数目,不是节点的数目)
    思路:算每个节点左边深度l=左节点深度+1,右边深度r=右节点深度+1,l+r和res对比取最大值。
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        res = 0
        def dfs(root):
            nonlocal res  # 外部嵌套函数内的变量。
            if not root:
                return 0
            l = dfs(root.left)
            r = dfs(root.right)
            res = max(res,l+r)
            return 1+max(l,r)
        dfs(root)
        return res
  1. 翻转二叉树
    思路:先把root.left和root.right调换位置,然后递归引用invertTree(root.left)和invertTree(root.right)
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return 
        root.left,root.right = root.right,root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root # return root别忘了。
  1. 合并二叉树
    思路:都有值:t1 = t1+t2,都没有返回none,t1,t2只有一个,则返回一个。
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
	def mergeTrees(self, t1, t2):
		"""
		:type t1: TreeNode
		:type t2: TreeNode
		:rtype: TreeNode
		"""
		def dfs(t1,t2):
			if not t1 or not t2:
				return t1 if t1 else t2
			t1.val += t2.val
			t1.left = dfs(t1.left,t2.left)
			t1.right = dfs(t1.right,t2.right)
			return t1
		return dfs(t1,t2)
  1. 路径总和(根到叶子节点路径和)
    思路:not root:False.如果root.val==sum and not root.left and not root.right,true。
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        if root.val == sum and not root.left and not root.right:
            return True
        return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)
  1. 路径总和 III(统计路径和等于一个数的路径数量)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def pathSum(self, root: TreeNode, sum: int) -> int:        
        def dfs(root, sumlist):
            if not root:
                return 0 # 这两句不要写在外面,递归函数里面是必须有这两句的
            sumlist = [num+root.val for num in sumlist]
            sumlist.append(root.val)
            counts = sumlist.count(sum)
            return counts + dfs(root.left, sumlist) + dfs(root.right, sumlist)
        return dfs(root, []) # 而不是dfs(root, []),return counts
  1. 子树(检验 s 中是否包含 t )
    思路:遍历(s,t),(s.left,t),(s.right,t)是否是isSubtree的树。再创建一个函数判断两个树是否isSametree。
# 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 isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
        if not s and not t:
            return True
        if not s or not t:
            return False
        return self.isSubtree(s.left,t) or self.isSubtree(s.right,t) or self.isSametree(s,t)

    def isSametree(self,s,t):
        if not s and not t:
            return True
        if not s or not t:
            return False
        if s.val != t.val:
            return False
        return self.isSametree(s.left,t.left) and self.isSametree(s.right,t.right)
  1. 对称二叉树
    思路:先判定root,再创建个helper函数,输入l和r,判断l和r是否存在、相等,递归调用。
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        def dfs(l,r):
            if not l and not r:
                return True
            elif not l or not r:
                return False
            elif l.val != r.val: # 用3个if也是可以的。
                return False
            else:
                return dfs(l.left,r.right) and dfs(r.left,l.right)
        return dfs(root.left,root.right)
  1. 二叉树的最小深度
    思路:dfs递归。not root:0, not root.left and not root.right: return 1, 都有:min(l,r),只存在一个就返回一个。
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        if root.left and root.right:
            return 1+min(self.minDepth(root.left),self.minDepth(root.right))
        elif root.left:
            return 1+self.minDepth(root.left)
        elif root.right:
            return 1+self.minDepth(root.right)
        else:
            return 1
  1. 统计左叶子节点的和(计算给定二叉树的所有左叶子之和)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sumOfLeftLeaves(self, root: TreeNode) -> int:
        if not root:
            return 0
        if root.left and not root.left.left and not root.left.right:
            return root.left.val+self.sumOfLeftLeaves(root.right)
        else:
            return self.sumOfLeftLeaves(root.left)+self.sumOfLeftLeaves(root.right)
  1. 相同节点值的最大路径长度(边数)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def longestUnivaluePath(self, root: TreeNode) -> int:
        res = 0
        def dfs(root):
            if not root: return 0
            nonlocal res
            l_length = dfs(root.left)
            r_length = dfs(root.right)
            l = r = 0
            if root.left and root.left.val == root.val:
                l = l_length + 1
            if root.right and root.right.val == root.val:
                r = r_length + 1
            res = max(res, l + r)
            return max(l, r)
        dfs(root)
        return res
  1. 间隔遍历(打家劫舍 III)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def rob(self, root: TreeNode) -> int:
        def dfs(root):
            if not root:
                return [0,0]
            l = dfs(root.left)
            r = dfs(root.right)
            return [max(l[0],l[1])+max(r[0],r[1]), root.val+l[0]+r[0]]  # [不偷,偷]。left[0]是root.left作为root,但不包括root.left下面的max(left)+max(right)
        return max(dfs(root))
  1. 二叉树中第二小的节点 (输出所有节点中的第二小的值)(第二种方法也有点难理解)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findSecondMinimumValue(self, root: TreeNode) -> int:
        s = set()
        def helper(root):
            if not root: 
                return
            s.add(root.val)
            helper(root.left)
            helper(root.right)
        helper(root)
        return sorted(s)[1] if len(s)>1 else -1
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findSecondMinimumValue(self, root: TreeNode) -> int:
        return self.helper(root,root.val)

    def helper(self,root,value):
        if not root:
            return -1
        if root.val>value:
            return root.val
        l=self.helper(root.left,value)
        r=self.helper(root.right,value)
        if l==-1:
            return r
        if r==-1:
            return l
        return min(r,l)
        # 问题可以转化为求左右子树的最小值,如果左右子树最小值都大于根节点的值取较小的值。其他情况取左右子树较大的值。

层次遍历
16. 一棵树每层节点的平均数

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

class Solution:
    def averageOfLevels(self, root: TreeNode) -> List[float]:
        if not root:
            return []
        cur_level = [root]
        res = []
        while cur_level:
            res.append(sum(node.val for node in cur_level) / len(cur_level))
            next_level = []                             
            for node in cur_level: 
                if node.left: 
                    next_level.append(node.left)  
                if node.right:                
                    next_level.append(node.right) 
            cur_level = next_level  
        return res
  1. 得到左下角的节点(在树的最后一行找到最左边的值)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        if not root: 
            return []
        cur_level, res = [root], None
        while cur_level:
            next_level, res = [], cur_level[0].val
            for node in cur_level:
                if node.left: 
                    next_level.append(node.left)
                if node.right: 
                    next_level.append(node.right)
            cur_level = next_level
        return res

前中后序遍历
18. 非递归实现二叉树的前序遍历

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

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        # 递归
        res = []
        def helper(root):
            if not root:
                return 
            res.append(root.val)
            helper(root.left)
            helper(root.right)
        helper(root)
        return res
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
    	# 迭代
        res = []
        if not root:
            return res
        stack = [root]
        while stack:
            node = stack.pop()
            res.append(node.val)
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
        return res
  1. 非递归实现二叉树的后序遍历
# 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 postorderTraversal(self, root: TreeNode) -> List[int]:
        # 递归
        res = []
        def helper(root):
            if not root:
                return 
            helper(root.left)
            helper(root.right)
            res.append(root.val)
        helper(root)
        return res
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
    	# 迭代
        res = []
        if not root:
            return res
        stack = [root]
        while stack:
            node = stack.pop()
            res.append(node.val)
            if node.left :
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
        return res[::-1]
  1. 非递归实现二叉树的中序遍历
# 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]:
        # 递归
        res = []
        def helper(root):
            if not root:
                return 
            helper(root.left)
            res.append(root.val)
            helper(root.right)
        helper(root)
        return res
# 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]:
        # 迭代
        res = []
        if not root:
            return []
        stack = []
        cur = root
        while stack or cur:
            while cur:
                stack.append(cur)
                cur = cur.left
            cur = stack.pop()
            res.append(cur.val)
            cur = cur.right
        return res

9.6 16.21看完了

二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点。
二叉查找树中序遍历有序。

BST
21. 修剪二叉查找树

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

class Solution:
    def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
        if not root:
            return
        if root.val < L:
            return self.trimBST(root.right,L,R)
        if root.val > R:
            return self.trimBST(root.left,L,R)
        root.left = self.trimBST(root.left,L,R)
        root.right = self.trimBST(root.right,L,R)
        return root
  1. 二叉搜索树中第K小的元素
    迭代
# 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 kthSmallest(self, root: TreeNode, k: int) -> int:
        cur = root
        stack = []
        while cur or stack:
            while cur:
                stack.append(cur)
                cur = cur.left
            tmp = stack.pop()
            k -= 1
            if k == 0:
                return tmp.val
            if tmp.right:
                cur = tmp.right

递归

# 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 kthSmallest(self, root: TreeNode, k: int) -> int:
        res = 0
        def helper(root):
            nonlocal k, res
            if root.left: 
                helper(root.left)
            k -= 1
            if k == 0: 
                res = root.val
                return 
            if root.right: 
                helper(root.right)
        helper(root)
        return res
  1. 把二叉查找树每个节点的值都加上比它大的节点的值
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def __init__(self):
        self.total = 0
     # 反序中序遍历。python2没有nonlocal,必须用def __init__(self):self.total = 0 
    def convertBST(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        def helper(root):
            nonlocal total
            if root:
                helper(root.right)
                self.total += root.val
                root.val = self.total
                helper(root.left)
            return root
        return helper(root)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def convertBST(self, root: TreeNode) -> TreeNode:
        total = 0
        def helper(root):
            nonlocal total  # python3可以用nonlocal.
            if root:  # 反序中序遍历
                helper(root.right)
                total += root.val
                root.val = total
                helper(root.left)
            return root
        return helper(root)
  1. 二叉查找树的最近公共祖先
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

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)
        if p.val>root.val and q.val>root.val:
            return self.lowestCommonAncestor(root.right,p,q)
        return root
  1. 二叉树的最近公共祖先
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
# 参考Krahets的题解。
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root or root == p or root == q: 
            return root
        l = self.lowestCommonAncestor(root.left, p, q)
        r = self.lowestCommonAncestor(root.right, p, q)
        if not l: 
            return r
        if not r: 
            return l
        return root
  1. 从有序数组中构造二叉查找树
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        def helper(l, r):  # 中序遍历:始终选择中间位置左边元素作为根节点
            if l > r:
                return 
            mid = l + (r - l) // 2
            root = TreeNode(nums[mid])
            root.left = helper(l, mid-1)
            root.right = helper(mid+1, r)  # 验证过,没错的。就是l<r时什么都不返回。
            return root
        return helper(0, len(nums)-1)
  1. 根据有序链表构造平衡的二叉查找树
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
# 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 sortedListToBST(self, head: ListNode) -> TreeNode:
        def findmid(head, tail):
            slow = head
            fast = head
            while fast != tail and fast.next!= tail:
                slow = slow.next
                fast = fast.next.next
            return slow
        
        def helper(head, tail):
            if head == tail: 
                return 
            node = findmid(head, tail)
            root = TreeNode(node.val)
            root.left = helper(head, node) # 左边一半利用tail来作为末尾点,右边一半用none作为末尾点,好办法。
            root.right = helper(node.next, tail)
            return root
            
        return helper(head, None)
  1. 在二叉查找树中寻找两个节点,使它们的和为一个给定值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findTarget(self, root: TreeNode, k: int) -> bool:
        map_set = set()
        stack = [root]
        while stack:
            node = stack.pop()
            if node:
                if k - node.val in map_set:
                    return True
                else:
                    map_set.add(node.val)
                    stack.append(node.right)
                    stack.append(node.left)
        return False
  1. 在二叉查找树中查找两个节点之差的最小绝对值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def getMinimumDifference(self, root: TreeNode) -> int:
        stack = []
        node = root
        pre = -float('inf')
        min_val = float('inf')
        while node or stack:
            while node:
                stack.append(node)
                node = node.left
            node = stack.pop()
            cur = node.val
            if cur - pre < min_val:
                min_val = cur - pre
            pre = cur
            node = node.right
        return min_val
  1. 寻找二叉查找树中出现次数最多的值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findMode(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        node = root
        stack = []
        res = []
        max_times = 1
        time = 1
        pre = float("inf")
        while node or stack:
            while node:
                stack.append(node)
                node = node.left
            node = stack.pop()
            cur = node.val
            if cur == pre:
                time += 1
            else:
                time = 1
                pre = cur
            if time == max_times:
                res.append(cur)
            if time > max_times:
                res = [cur]
                max_times = time
            node = node.right     
        return res

9.7看完了 9.10看完了,9.11看完了

Trie:又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种字符串前缀。
31. 实现一个 Trie(没怎么看懂)

class Trie(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.d = {}

    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: None
        """
        tree = self.d # 起别名,然后不断覆盖这个别名,对tree所有的操作都会在self.d上也操作一次
        for a in word:
            if a not in tree:
                tree[a] = {}
            tree = tree[a] # key是字符,value是字典,每个字典相当于树的节点,tree=tree[a]把指针移到下个字符的节点。
        tree["#"] = "#"

    def search(self, word):
        """
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        tree = self.d
        for a in word:
            if a not in tree:
                return False
            tree = tree[a]
        if "#" in tree:
            return True
        return False


    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        tree = self.d
        for a in prefix:
            if a not in tree:
                return False
            tree = tree[a]
        return True
  1. 实现一个 Trie,用来求前缀和(没怎么看懂)
class MapSum:
    def __init__(self):
        self.d = {}

    def insert(self, key: str, val: int) -> None:
        tree = self.d
        for c in key:
            if c not in tree:
                tree[c] = {}
            tree = tree[c]            # 字典迭代
        tree['val'] = val          # 迭代终点赋值

    def sum(self, prefix: str) -> int:
        tree = self.d
        for c in prefix:
            if c not in tree:
                return 0        # 判断前缀是否存在
            tree = tree[c]
        res = 0
        def dfs(tree):
            for c in tree:
                if c == 'val':
                    nonlocal res
                    res += tree[c] # 前缀求和
                else:
                    dfs(tree[c])
        dfs(tree)
        return res


# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值