Tree真題

[骨骼清奇]n-array tree, 給一個(gè)node 算出包括這個(gè)node在內(nèi)的所有child的sum
[骨骼清奇]n-array tree统扳,給一個(gè)node 打印出從這node出發(fā)的所有path. 問了時(shí)間復(fù)雜度和空間復(fù)雜度菩收。
[骨骼清奇]第一輪問了兩題填硕,第一題是一個(gè)數(shù)組盅粪,在某個(gè)位置前元素單調(diào)遞增堪夭,然后單調(diào)遞減咏删,就是那種元素大小像山一樣形狀的數(shù)組惹想,然后求最大最小值,用binary search做督函,然后第二題是比較二叉樹是否相同嘀粱,問了一下時(shí)間復(fù)雜度。

[骨骼清奇]Write a function to detect if two trees are isomorphic.
給定兩顆樹辰狡,判斷它們是否有相同的shape.
follow up:如果允許樹的節(jié)點(diǎn)擁有任意數(shù)目的父節(jié)點(diǎn)锋叨,如何判斷?
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
轉(zhuǎn)移關(guān)系:1到n中選定某個(gè)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的根節(jié)點(diǎn)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的數(shù)值是0-N-1,構(gòu)成一顆樹叫倍,ans[i]表示從i出發(fā)到其他所有nodes的edges數(shù)之和偷卧。ans[0] = 1+1+2+2+2 = 8
重點(diǎn)是找到關(guān)系edge AB在最終答案里的關(guān)系:ans[B] = ans[A] + Nodes_A - Nodes_B。因?yàn)锳B是直接相連的吆倦,那么從B出發(fā)听诸,對于以B為根節(jié)點(diǎn)的nodes而言,ans[A]里面每一個(gè)都多加了1蚕泽,那個(gè)1就是edgeAB晌梨,因此要減掉Nodes_B。同樣的须妻,ans[A]還需要加上Nodes_A, 因?yàn)閺腂出發(fā)需要經(jīng)過BA仔蝌,而從A出發(fā)不用。

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荒吏?其實(shí)是相對于root這個(gè)symmetric axis的位置敛惊,只要turn right就加一,turn left減一司倚,再把這個(gè)表示相對位置的Index放入一個(gè)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 index<Gmin:Gmin = index
            if index>Gmax: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出發(fā)鸵鸥,left child不停的入棧奠滑,直到遇到一個(gè)Node沒有l(wèi)eft child(可能是leaf也可能不是),這就是我們in-order traversal的第一站妒穴,然后以它的left child作為root宋税,重復(fù)剛剛那一套流程。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.val<key:
            self.replace(cur,cur.right,key)
        elif cur.val>key:
            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<key:
                prev.right = cur.left or cur.right
            else:
                prev.left = cur.left or cur.right

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讼油,一起剝皮案震驚了整個(gè)濱河市杰赛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矮台,老刑警劉巖乏屯,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘦赫,居然都是意外死亡辰晕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門确虱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來含友,“玉大人,你說我怎么就攤上這事校辩【轿剩” “怎么了?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵宜咒,是天一觀的道長南缓。 經(jīng)常有香客問我,道長荧呐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任纸镊,我火速辦了婚禮倍阐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逗威。我一直安慰自己峰搪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布凯旭。 她就那樣靜靜地躺著概耻,像睡著了一般使套。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鞠柄,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天侦高,我揣著相機(jī)與錄音,去河邊找鬼厌杜。 笑死奉呛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的夯尽。 我是一名探鬼主播瞧壮,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼匙握!你這毒婦竟也來了咆槽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤圈纺,失蹤者是張志新(化名)和其女友劉穎秦忿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赠堵,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡小渊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茫叭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酬屉。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖揍愁,靈堂內(nèi)的尸體忽然破棺而出呐萨,到底是詐尸還是另有隱情,我是刑警寧澤莽囤,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布谬擦,位于F島的核電站,受9級特大地震影響朽缎,放射性物質(zhì)發(fā)生泄漏惨远。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一话肖、第九天 我趴在偏房一處隱蔽的房頂上張望北秽。 院中可真熱鬧,春花似錦最筒、人聲如沸贺氓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辙培。三九已至蔑水,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扬蕊,已是汗流浹背搀别。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厨相,地道東北人领曼。 一個(gè)月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蛮穿,于是被迫代替她去往敵國和親庶骄。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,309評論 0 10
  • 時(shí)間總是感覺一轉(zhuǎn)眼践磅,每天早早起床做早餐单刁,無論一家人持多少,總是希望孩子的記憶中一直有媽媽做早餐的情景府适,記住媽媽做飯...
    倆寶的媽咪閱讀 114評論 0 0
  • 《孫子兵法》第二篇作戰(zhàn)篇核心思想是速戰(zhàn)羔飞。 孫子的邏輯順序,先是廟算檐春、“五事七計(jì)”逻淌,看有沒有勝算。勝算在握疟暖,決定打了...
    潘武閱讀 1,436評論 0 3
  • 姓名:潘亞平 公司:福建起步兒童用品有限公司 日精進(jìn)打卡第59天 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》2遍共60遍 《大學(xué)》...
    徒手敬歲月_114e閱讀 84評論 0 0
  • 舊文新發(fā)呀卡儒,去年關(guān)于內(nèi)存結(jié)構(gòu)分析的學(xué)習(xí)筆記,今年再看清楚了很多俐巴,發(fā)粗來~ 1. 堆骨望、棧、池 首先來段代碼: 可以發(fā)...
    公子七閱讀 930評論 2 4