Tree真题

[骨骼清奇]n-array tree, 给一个node 算出包括这个node在内的所有child的sum
[骨骼清奇]n-array tree,给一个node 打印出从这node出发的所有path. 问了时间复杂度和空间复杂度。
[骨骼清奇]第一轮问了两题,第一题是一个数组,在某个位置前元素单调递增,然后单调递减,就是那种元素大小像山一样形状的数组,然后求最大最小值,用binary search做,然后第二题是比较二叉树是否相同,问了一下时间复杂度。

[骨骼清奇]Write a function to detect if two trees are isomorphic.
给定两颗树,判断它们是否有相同的shape.
follow up:如果允许树的节点拥有任意数目的父节点,如何判断?
Two trees are called isomorphic if one of them can be obtained from other by a series of flips, i.e. by swapping left and right children of a number of nodes. Any number of nodes at any level can have their children swapped. Two empty trees are isomorphic.

def isIsomorphic(n1, n2): 
    if n1 is None and n2 is None: 
        return True
  
    if n1 is None or n2 is None: 
        return False
  
    if n1.data != n2.data : 
        return False

    # Case 1: subtrees NOT  "Flipped". 
    # Case 2: subtrees "Flipped" 
    return ((isIsomorphic(n1.left, n2.left)and 
            isIsomorphic(n1.right, n2.right)) or
            (isIsomorphic(n1.left, n2.right) and 
            isIsomorphic(n1.right, n2.left)) 
            ) 

Time Complexity: The above solution does a traversal of both trees. So time complexity is O(m + n) where m and n are number of nodes in given trees.

Follow up: general tree?
If swap with either two siblings, then we can compare level by level using permutation of node values.

LC 226 Invert Binary Tree 二叉树的镜像(Symmetric Tree)
Recursion:

class Solution:
    def Mirror(self, root):
        if root == None:
            return 
        self.Mirror(root.left)
        self.Mirror(root.right)
        root.left,root.right = root.right,root.left

Iterative way:
The idea is that we need to swap the left and right child of all nodes in the tree. So we create a queue to store nodes whose left and right child have not been swapped yet. Initially, only the root is in the queue. As long as the queue is not empty, remove the next node from the queue, swap its children, and add the children to the queue. Null nodes are not added to the queue. Eventually, the queue will be empty and all the children swapped, and we return the original root.

class Solution:
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return root
        level=[root]
        while level:
            for node in level:
                node.left,node.right = node.right,node.left
            level = [kid for node in level for kid in (node.left,node.right) if kid]
        return root

LC 102Binary Tree Level Order Traversal

class Solution:
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        ans,level = [],[root]
        while level:
            ans.append([node.val for node in level])
            level = [ kid for n in level for kid in (n.left,n.right) if kid]
        return ans

LC 105. Construct Binary Tree from Preorder and Inorder Traversal

class Solution:
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if inorder:
            root_ind = inorder.index(preorder.pop(0))
            root = TreeNode(inorder[root_ind])
            root.left = self.buildTree(preorder, inorder[0:root_ind])
            #preorder now only contains nodes in right sub-tree of root
            root.right = self.buildTree(preorder, inorder[root_ind+1:])
            return root

LC 106. Construct Binary Tree from Inorder and Postorder Traversal

class Solution:
    def buildTree(self, inorder, postorder):
        if inorder:
            root_ind = inorder.index(postorder.pop())
            root = TreeNode(inorder[root_ind])
            root.right = self.buildTree(inorder[root_ind+1:],postorder)
            root.left = self.buildTree(inorder[:root_ind],postorder)
            return root

[骨骼清奇] LC 96 Unique Binary Search Trees
转移关系:1到n中选定某个i作为root!

class Solution: #beat 100%
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<1: return 0
        F = [0]*(n+1)
        F[0] = F[1] = 1
        for i in range(2,n+1):
            for j in range(i):
                F[i] += F[j]*F[i-j-1]
        return F[n]

LC95 unique binary search tree II
需要返回所有不同BST的根节点list. 用Recursion做。

class Solution:
    def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        def generate_trees(start, end):
            if start > end:
                return [None,]
            
            all_trees = []
            for i in range(start, end + 1):  # pick up a root
                # all possible left subtrees if i is choosen to be a root
                left_trees = generate_trees(start, i - 1)
                
                # all possible right subtrees if i is choosen to be a root
                right_trees = generate_trees(i + 1, end)
                
                # connect left and right subtrees to the root i
                for l in left_trees:
                    for r in right_trees:
                        current_tree = TreeNode(i)
                        current_tree.left = l
                        current_tree.right = r
                        all_trees.append(current_tree)
            
            return all_trees
        
        return generate_trees(1, n) if n else []

[骨骼清奇] LC 834 Sum of Distances in Tree
Input: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
Output: [8,12,6,10,10,10]
Nodes的数值是0-N-1,构成一颗树,ans[i]表示从i出发到其他所有nodes的edges数之和。ans[0] = 1+1+2+2+2 = 8
重点是找到关系edge AB在最终答案里的关系:ans[B] = ans[A] + Nodes_A - Nodes_B。因为AB是直接相连的,那么从B出发,对于以B为根节点的nodes而言,ans[A]里面每一个都多加了1,那个1就是edgeAB,因此要减掉Nodes_B。同样的,ans[A]还需要加上Nodes_A, 因为从B出发需要经过BA,而从A出发不用。

class Solution:
    def sumOfDistancesInTree(self, N, edges):
        """
        :type N: int
        :type edges: List[List[int]]
        :rtype: List[int]
        """
        graph = self.buildGraph(N,edges)
        seen = set()
        cnts = [1]*N
        dist = [0]*N
        self.dfs(graph,0,dist,cnts,seen)
        #dist[0] is the chosen root and it is answered now!
        seen = set() 
        self.dfs2(graph,0,dist,cnts,seen,N)
        return dist

    def buildGraph(self,N,edges):
        from collections import defaultdict
        graph = defaultdict(list)
        for i,j in edges:
            graph[i].append(j)
            graph[j].append(i)
        return graph


    def dfs(self,graph,i,dist,cnts,seen):
        seen.add(i)
        for j in graph[i]:
            if j in seen:continue
            self.dfs(graph,j,dist,cnts,seen)
            cnts[i] += cnts[j]
            dist[i] += dist[j] + cnts[j]
            #cnts[j] means node i is one edge further
 
    def dfs2(self,graph,i,dist,cnts,seen,n):
        seen.add(i)
        for j in graph[i]:
            if j in seen:continue
            dist[j] = dist[i] - cnts[j] + (n - cnts[j])
            self.dfs2(graph,j,dist,cnts,seen,n)

https://blog.csdn.net/tinkle181129/article/details/79326023

[Uber] LC 314 Binary Tree Vertical Order Traversal
分析:如何判断nodes属于同一层vertical Order?其实是相对于root这个symmetric axis的位置,只要turn right就加一,turn left减一,再把这个表示相对位置的Index放入一个hash table,然后按照index从小打到输出即可!

from collections import deque, defaultdict

class Solution(object):
    def verticalOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []

        table = defaultdict(list)
        queue = deque()

        # put node and the level that it belongs to
        queue.append((root, 0))
        Gmin = Gmax = 0
        while queue:
            node, index = queue.popleft()
            if indexGmax:Gmax = index
            table[index].append(node.val)

            if node.left:
                queue.append((node.left, index-1))

            if node.right:
                queue.append((node.right, index+1))

        # The keys of the table are the indices, sort it min to max
        # return [table[index] for index in sorted(table)]

        return [table[index] for index in range(Gmin,Gmax+1)]

LC 101 Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
General Tree:
left = arr[:len(arr)//2]
right = arr[:len(left):-1]

[骨骼清奇]考察二叉树,自己定义tree node,然后自己把二叉树各种遍历方法写一下,递归的和非递归的。

LC 94 Binary Tree Inorder Traversal
Recursion:

def inorderTraversal1(self, root):
    res = []
    self.helper(root, res)
    return res
    
def helper(self, root, res):
    if root:
        self.helper(root.left, res)
        res.append(root.val)
        self.helper(root.right, res)

Iterative (stack):从root出发,left child不停的入栈,直到遇到一个Node没有left child(可能是leaf也可能不是),这就是我们in-order traversal的第一站,然后以它的left child作为root,重复刚刚那一套流程。For each leaf, its left null child will help print the value of itself, and its null right child will help print the correspondent successor (could be an ancestor far above).

class Solution:
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stk = []
        ans = []
        node = root    
        while (node is not None) or stk:  # empty lists are falsy
            if node is not None:
                stk.append(node)
                node = node.left
            else:
                node = stk.pop()
                ans.append(node.val)
                node = node.right
        return ans

LC 230 Kth Smallest Element in a BST

class Solution:

    def kthSmallest(self, root, k):
        self.k = k
        self.in_order(root)
        return self.result

    def in_order(self, node):
        if not node:
            return None
        self.in_order(node.left)
        self.k -= 1
        if self.k == 0:
            self.result=node.val
            return
        self.in_order(node.right)

Iterative:

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        cnt,stack = 0,[]
        node = root
        while node is not None or stack:
            if node is not None:
                stack.append(node)
                node=node.left
            else:
                node=stack.pop()
                cnt += 1
                if cnt==k: return node.val
                node=node.right

LC 144 Binary Tree Preorder Traversal
Beat 100%

class Solution:
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        ans,stack = [],[]
        node = root
        while node is not None or stack:
            if node is not None:
                ans.append(node.val)
                #get value before going to children
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                node=node.right
        return ans

LC 145 Binary Tree Postorder Traversal

class Solution:
    def postorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """

        ans,stack = [],[]
        node = root
        while node is not None or stack:
            if node is not None:
                #ans.insert(0,node.val) #reverse preorder
                ans.append(node.val)
                stack.append(node)
                node = node.right #reverse preorder
            else:
                node = stack.pop()
                node = node.left #reverse preorder
        return ans[::-1]

[Uber]LC 450 Delete Node in a BST

1.When found the node, put right child of the node to the right of [the right most leaf node of left child][max value of left sub-tree but still smaller then any value in right sub tree]. That way the values are still in order.
2.Return the left child of the node(skip root, a.k.a delete it). If the node doesn't have left child, return right child.
3.Otherwise do binary search. If key < root.val, change left child to the returned new root. Do right child if key > root.val.

This solution always runs in O(log(n)) time since when it finds the node to delete, it goes to the right most leaf of the left sub-tree to put right sub-tree of the node there.

Modify and not return any node in recursion, beat 100%!

class Solution:
    def deleteNode(self, root, key):
        dummy = TreeNode(float('INF'))
        dummy.left = root
        self.replace(dummy,root,key)
        return dummy.left

    def replace(self,prev,cur,key):
        if not cur: return
        if cur.valkey:
            self.replace(cur,cur.left,key)
        else:#FOUND
            if cur.left:
                left_right_most = cur.left
                while left_right_most.right:
                    left_right_most = left_right_most.right
                left_right_most.right=cur.right
            
            if prev.val

Slower Version without prev

class Solution(object):
    def deleteNode(self, root, key):
        if not root: return None
        
        if root.val == key:
            if root.left:
                # Find the right most leaf of the left sub-tree
                left_right_most = root.left
                while left_right_most.right:
                    left_right_most = left_right_most.right
                # Attach right child to the right of that leaf
                left_right_most.right = root.right
                # Return left child instead of root, a.k.a delete root
                return root.left
            else:
                return root.right
        # If left or right child got deleted, the returned root is the child of the deleted node.
        elif root.val > key:
            root.left = self.deleteNode(root.left, key)
        else:
            root.right = self.deleteNode(root.right, key)
            
        return root

[GoogleCall]Delete Treenode, all are put in an array. parent 0 has children 1 and 2.

LC 428 N-ary tree

你可能感兴趣的:(Tree真题)