程序員代碼面試指南 python實現(第三章:二叉樹問題)

程序員代碼面試指南 python實現(第三章:二叉樹問題)

程序員代碼面試指南 python實現(第三章:二叉樹問題)

分別用遞歸和非遞歸方式實現二叉樹先序、中序和後序遍歷

在這裏插入圖片描述

二叉樹先序遍歷

遞歸

    def preOrderRecur(self,head):
        if head == None:
            return
        print(str(head.val)+" ")
        self.preOrderRecur(head.left)
        self.preOrderRecur(head.right)

非遞歸

在這裏插入圖片描述
在這裏插入圖片描述

	def preOrderUnRecur(self,head):
		if head != None:
			stack = []
			stack.append(head)
			while len(stack) != 0:
				head = stack.pop()
				print(str+" ")
				if head.right != None:
					stack.append(head.rigth)
				if head.left != None:
					stack.append(head.left)

二叉樹中序遍歷

遞歸

 def inOrderRecur(self,head):
        if head == None:
            return
        self.inOrderRecur(head.left)
        print(str(head.val)+" ")
        self.inOrderRecur(head.right)

非遞歸

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

	def inOrderUnRecur(self,head):
		if head != None:
			stack = []
			while len(stack) != 0 or head != None:
				if head != None:
					stack.append(head)
					head = head.left
				else:
					head = stack.pop()
					print(str(head.val)+" ")
					head = head.right 

二叉樹後序遍歷

遞歸

	def posOrderRecur(self,head):
		if head == None:
			return
		self.posOrderRecur(head.left)
		self.posOrderRecur(head.right)
		print(str(head.val)+" ")

非遞歸

兩個棧
	def posOrderUnRecur1(self,head)
		if head != None:
			s1 = []
			s2 = []
			s1.append(head)
			while len(s1) != 0:
				head = s1.pop()
				s2.append(head)
				if head.left != None:
					s1.appned(head.left)
				if head.right != None:
					s1.append(head.right)
			while len(s2) != 0:
				print(str(s2.pop().val) + " ")
				
一個棧
 def posOrderUnRecur2(self,head):
        if head != None:
            stack = []
            stack.append(head)
            while len(stack) != 0:
                c = stack[-1]
                if c.left != None and head != c.left and head != c.right:
                    stack.append(c.left)
                elif c.right != None and head != c.right:
                    stack.append(c.right)
                else:
                    print(str(stack.pop().val)+" ")
                    head = c

打印二叉樹的邊界節點

在這裏插入圖片描述
在這裏插入圖片描述

標準一

在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def printEdge1(self,head):
        if head == None:
            return
        height = self.getHeght(head,0)
        edgeMap = [[-1]*2]*height
        self.setEdgeMap(head,0,edgeMap)
        # 打印左邊界
        for i in range(0,len(edgeMap)):
            print(edgeMap[i][0].val + " ")
        # 打印非邊界的葉子節點
        self.printLeafNotInMap(head,0,edgeMap)
        #打印右邊界
        for i in range(len(edgeMap)-1,-1,-1):
            if edgeMap[i][0] != edgeMap[i][1]:
                print(edgeMap[i][1].val + " ")


    def getHeght(self,head,l):
        if head == None:
            return l
        return max(self.getHeght(head.left,l+1),self.getHeght(head.right,l+1))


    def setEdgeMap(self,head,l,edgeMap):
        if head == None:
            return
        edgeMap[1][0] = head if edgeMap[1][0] == None else edgeMap[1][0]
        edgeMap[1][1] = head
        self.setEdgeMap(head.left,l+1,edgeMap)
        self.setEdgeMap(head.right,l+1,edgeMap)

    def printLeafNotInMap(self,head,l,m):
        if head == None:
            return
        if head.left == None and head.right == None and head != m[1][0] and head != m[l][l]:
            print(head.val + " ")
        self.printLeafNotInMap(head.left,l+1,m)
        self.printLeafNotInMap(head.right,l+1,m)



標準二

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

如何較爲直觀地打印二叉樹

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

二叉樹的序列化和反序列化

在這裏插入圖片描述

通過先序遍歷

序列化

    def serialByPre(self,head):
        if head == None:
            return "#!"
        res = head.val + "!"
        res += self.serialByPre(head.left)
        res += self.serialByPre(head.right)
        return res

反序列化

 	def reconByPreString(self,preStr):
        values = preStr.split("!")
        queue = []
        for i in range(0,len(values)):
            queue.append(values[i])

        return self.reconPreOrder(queue)

    def reconPreOrder(self,queue):
        value = queue.pop(0)
        if value == "#":
            return None
        head = TreeNode(int(value))
        head.left = self.reconPreOrder(queue)
        head.right = self.reconPreOrder(queue)
        return head

通過層遍歷實現

在這裏插入圖片描述
在這裏插入圖片描述
序列化

 def serialByLevel(self,head):
        if head == None:
            return "#!"
        res = head.val + "!"
        queue = []
        queue.append(head)
        while len(queue) != 0:
            head = queue.pop(0)
            if head.left != None:
                res += head.left.val + "!"
                queue.append(head.left)
            else:
                res += "#!"
            if head.right != None:
                res += head.right.val + "!"
                queue.append(head.right)
            else:
                res += "#!"
        return res

反序列化

    def reconByLevelString(self,levelStr):
        values = levelStr.split("!")
        index = 0
        
        head = self.generateNodeByString(values[index])
        index += 1
        queue = []
        if head != None:
            queue.append(head)
        while len(queue) != 0:
            node = queue.pop(0)
            node.left = self.generateNodeByString(values[index])
            index += 1
            node.right = self.generateNodeByString(values[index])
            index += 1
            if node.left != None:
                queue.append(node.left)
            if node.right != None:
                queue.append(node.right)
                
        return head
            
            

    def generateNodeByString(self,val):
        if val == "#":
            return None
        return TreeNode(int(val))

遍歷二叉樹的神級方法

在二叉樹中找到累加和爲指定值的最長路徑長度

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def getMaxLength(self,head,sum):
        sumMap = {}
        sumMap[0] = 0
        return self.preOrder(head,sum,0,1,0,sumMap)

    def preOrder(self,head,sum,preSum,level,maxLen,sumMap):
        if head == None:
            return maxLen
        curSum = preSum + head.val
        if curSum not in sumMap.keys():
            sumMap[curSum]=level
        if (curSum-sum) in sumMap.keys():
            maxLen = max(level-sumMap[(curSum-sum)],maxLen)
        maxLen = self.preOrder(head.left,sum,curSum,level+1,maxLen,sumMap)
        maxLen = self.preOrder(head.right,sum,curSum,level+1,maxLen,sumMap)
        if level == sumMap[curSum]:
            sumMap.pop(curSum)
        return maxLen

if __name__ == "__main__":
    node1 = TreeNode(-3)
    node2 = TreeNode(3)
    node3 = TreeNode(-9)
    node4 = TreeNode(1)
    node5 = TreeNode(0)
    node6 = TreeNode(2)
    node7 = TreeNode(1)
    node8 = TreeNode(1)
    node9 = TreeNode(6)

    node1.left = node2
    node1.right = node3
    node2.left = node4
    node2.right = node5
    node3.left = node6
    node3.right = node7
    node5.left = node8
    node5.right = node9

    solu = Solution()
    print(solu.getMaxLength(node1,6))

找到二叉樹中的最大搜索二叉樹子樹

在這裏插入圖片描述
在這裏插入圖片描述

class Node(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None


class Solution(object):
    def biggestSubBST(self,head):
        record = [-1]*3
        return self.posOrder(head,record)
    def posOrder(self,head,record):
        if head == None:
            record[0] = 0
            record[1] = float('inf')
            record[2] = float('-inf')
            return  None
        value = head.val
        left = head.left
        right = head.right

        leftBST = self.posOrder(left,record)
        leftSize = record[0]
        leftMin = record[1]
        leftMax = record[2]

        rightBST = self.posOrder(right,record)
        rightSize = record[0]
        rightMin = record[1]
        rightMax = record[2]

        record[1] = min(leftMin,value)
        record[2] = max(rightMax,value)

        if left == leftBST and right == rightBST and leftMin < value and value < rightMin:
            record[0] = leftSize + rightSize + 1
            return head


        record[0] = max(leftSize,rightSize)
        return leftBST if leftSize > rightSize else rightBST


二叉樹的按層打印與ZigZag打印

在這裏插入圖片描述
在這裏插入圖片描述

按層次打印

在這裏插入圖片描述

	def printByLevel(self,head):
		if head == None:
			return
		queue = []
		level = 1
		last = head
		nLast = None
		queue.append(head)
		print("Level "+ str(level)+" : ")
		level += 1
		while len(queue) != 0:
			head = queue.pop(0)
			print(str(head.val)+" ")
			if head.left != None:
				queue.append(head.left)
				nLast = head.left
			if head.right != None:
				queue.append(head.right)
				nLast = head.right
			if head == last and len(queue) != 0:
				print("Level "+ str(level) + " : ")
				level += 1
				last = nLast
				

ZigZag打印

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

    def printByZigzag(self,head):
        if head == None:
            return
        dq = collections.deque()
        level = 1
        lr = True
        last = head
        nLast = None
        dq.appendleft(head)
        self.pringLevelAndOrientation(level,lr)
        level += 1
        while len(dq) != 0:
            if lr:
                head = dq.popleft()
                if head.left != None:
                    nLast = head.left if nLast == None else nLast
                    dq.append(head.left)
                if head.right != None:
                    nLast = head.right if nLast == None else nLast
                    dq.append(head.right)
            else:
                head = dq.pop()
                if head.right != None:
                    nLast = head.right if nLast == None else nLast
                    dq.appendleft(head.right)
                if head.left != None:
                    nLast = head.left if nLast == None else nLast
                    dq.appendleft(head.left)

            print(str(head.val)+" ")
            if head == last and len(dq) != 0:
                lr = not lr
                last = nLast
                nLast = None
                print(" ")
                self.pringLevelAndOrientation(level,lr)
                level += 1


    def pringLevelAndOrientation(self,level,lr):
        print("Level "+ str(level) + " from ")
        if lr:
            print("left to right:")
        else:
            print("right to left")

調整搜索二叉樹中兩個錯誤的節點

在這裏插入圖片描述

判斷t1樹是否包含t2樹全部的拓撲結構

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def contains(self,t1,t2):
        return self.check(t1,t2) or self.check(t1.left,t2) or self.check(t1.right,t2)


    def check(self,h,t2):
        if t2 == None:
            return True
        if h == None or h.val != t2.val:
            return False
        return self.check(h.left,t2.left) and self.check(h.right,t2.right)
        

判讀t1樹中是否有與t2樹拓撲結構完全的子樹

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入代碼片

判斷二叉樹是否爲平衡二叉樹

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

solution(object):
	def isBalance(self,head):
		res = True
		self.getHeight(head,1,res)
		return res
	
	def getHeight(self,head,level,res):
		if head == None:
			return level
		leftH = self.getHeight(head.left,level + 1,res)
		if not res:
			return level
		
		rightH = self.getHeight(head.right,level+1,res)
		if not res:
			return level

		if abs(leftH-rightH) > 1:
			res =False
		return max(leftH,rightH)
		

根據後序數組重建搜索二叉樹

在這裏插入圖片描述

原問題

在這裏插入圖片描述

solution(object):
	def isPostArray(self,arr):
		if arr == None or len(arr) == 0:
			return False
		return self.isPost(arr,0,len(arr)-1)
	def isPost(self,arr,start,end):
		if start == end:
			return True
		less = -1
		more = end
		for i in range(start,end):
			if arr[end] > arr[i]:
				less = i
			else:
				more = i if more == end else more
		if less == -1 or more == end:
			return self.isPost(arr,start,end-1)
		if less != more - 1:
			return False
		return self.isPost(arr,start,less) and self.isPost(arr,more,end-1)

進階

在這裏插入圖片描述
在這裏插入圖片描述

class Solution2(object):
    def posArrayToBST(self,posArr):
        if posArr == None:
            return None
        return self.posToBST(posArr,0,len(posArr)-1)
    
    def posToBST(self,posArr,start,end):
        if start > end:
            return None
        head = Node(posArr[end])
        less = -1
        more = end
        for i in range(start,end):
            if posArr[end] > posArr[i]:
                less = i
            else:
                more = i if more == end else more
        head.left = self.posToBST(posArr,start,less)
        head.right = self.posToBST(posArr,more,end-1)
        return head

判斷一棵樹是否爲搜索二叉樹和完全二叉樹

在這裏插入圖片描述

判斷搜索二叉樹

在這裏插入圖片描述

class TreeNode(object):
	def __init__(self,x):
		self.val = x
		self.left = None
		self.right = None
class Solution(object):
	def isBST(self,head):
		if head == None:
			return True
		res = True
		pre = None
		cur1 = head
		cur2 = None
		while cur1 != None:
			cur2 = cur1.left
			if cur2 != None:
				while cur2.right != None and cur2.right != cur1:
					cur2 = cur2.right
				if cur2.right == None:
					cur2.right = cur1
					cur1 = cur1.left
					continue
				else:
					cur2.right = None
			if pre != None and pre.val > cur1.val:
				res = False
			pre = cur1
			cur1 = cur1.right
		return res

判斷完全二叉樹

在這裏插入圖片描述

    def isCBT(self,head):
        if head == None:
            return True
        queue = []
        leaf = False
        l = None
        r = None
        queue.append(head)
        while len(queue) != 0:
            head = queue.pop(0)
            l = head.left
            r = head.right
            if leaf and (l != None or r != None) or (l == None and r != None):
                return False
            

            if l != None:
                queue.append(l)

            if r != None:
                queue.append(r)

            else:
                leaf = True
        return True

通過有序數組生成平衡搜索二叉樹

在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None
        
class Solution(object):
    def generateTree(self,sortArr):
        if sortArr == None:
            return None
        return self.generate(sortArr,0,len(sortArr)-1)
        
        
    def generate(self,sortArr,start,end):
        if sortArr == None:
            return None
        mid = (start+end)//2
        head = TreeNode(sortArr[mid])
        head.left = self.generate(sortArr,start,mid - 1)
        head.right = self.generate(sortArr,mid+1,end)
        return head

在二叉樹中找到一個節點的後繼節點

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None
        self.parent = None
        
class Solution(object):

    def getNextNode(self,node):
        if node == None:
            return node
        if node.right != None:
            return self.getLeftMost(node.right)
        else:
            parent = node.parent
            while parent != None and parent != node:
                node = parent
                parent = node.parent
            return parent

    def getLeftMost(self,node):
        if node == None:
            return None
        while node.left != None:
            node = node.left
        return node

在二叉樹中找到兩個節點的最近公共祖先

在這裏插入圖片描述
在這裏插入圖片描述

原問題

在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
	def __init__(self,x):
		self.val = x
		self.left = None
		self.right = None

class Solution(object):
	def lowestAncestor(self,head,o1,o2):
		if head == None or head == o1 or hed == o2:
			return head
		left = self.lowestAncestor(head.left,o1,o2)
		right = self.lowestAncestor(head.right,o1,o2)
		
		if left != None and right != None:
			return head
		if left != None:
			return left
		else:
			return right 

if __name__ == "__main__":
    node1 = TreeNode(1)
    node2 = TreeNode(2)
    node3 = TreeNode(3)
    node4 = TreeNode(4)
    node5 = TreeNode(5)
    node6 = TreeNode(6)
    node7 = TreeNode(7)
    node8 = TreeNode(8)

    node1.left = node2
    node1.right = node3
    node2.left = node4
    node2.right = node5
    node3.left = node6
    node3.right = node7
    node7.left = node8

    solu = Solution()
    print(solu.lowestAncestor(node1,node6,node8).val)

進階

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入代碼片

再進階:Tarjan算法與並查集解決二叉樹節點間最近公共祖先的批量查詢問題

二叉樹節點間的最大距離問題

在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def maxDistance(self,head):
        record = 0
        return self.posOrder(head,record)


    def posOrder(self,head,record):
        if head == None:
            record = 0
            return 0
        leftMax = self.posOrder(head.left,record)
        maxfromLeft = record
        rightMax = self.posOrder(head.right,record)
        maxfromRight = record
        curNodeMax = maxfromLeft + maxfromRight + 1
        record = max(maxfromLeft,maxfromRight) + 1
        return max(max(leftMax,rightMax),curNodeMax)



if __name__ == "__main__":
    solu = Solution()


    node1 = TreeNode(1)
    node2 = TreeNode(2)
    node3 = TreeNode(3)
    node4 = TreeNode(4)
    node5 = TreeNode(5)
    node6 = TreeNode(6)
    node7 = TreeNode(7)

    node1.left = node2
    node1.right = node3
    node2.left = node4
    node2.right = node5
    node3.left = node6
    node3.right = node7

    print(solu.maxDistance(node1))

先序、中序和後序數組兩兩結合重構二叉樹

在這裏插入圖片描述
在這裏插入圖片描述

先序與中序結合

在這裏插入圖片描述
在這裏插入圖片描述

class Solution(object):


    # 前序和中序
    def preInToTree(self,preOrder,inOrder):
        if preOrder == None or inOrder == None:
            return None
        dict = {}
        for i in range(0,len(inOrder)):
            dict[inOrder[i]] = i
        return self.preIn(preOrder,0,len(preOrder)-1,inOrder,0,len(inOrder)-1,dict)


    def preIn(self,p,pi,pj,n,ni,nj,dict):
        if pi > pj:
            return None
        head = TreeNode(p[pi])
        index = dict[p[pi]]
        head.left = self.preIn(p,pi+1,pi+index-ni,n,ni,index-1,dict)
        head.right = self.preIn(p,pi+index-ni+1,pj,n,index+1,nj,dict)
        return head

中序與後續結合

在這裏插入圖片描述

    # 中序和後序

    def inPosTOTree(self,inOrder,posOrder):
        if inOrder == None or posOrder == None:
            return None
        dict = {}
        for i in range(0,len(inOrder)):
            dict[inOrder[i]] = i
        return self.inPos(inOrder,0,len(inOrder)-1,posOrder,0,len(posOrder),dict)

    def inPos(self,n,ni,nj,s,si,sj,dict):
        if si > sj:
            return None
        head = TreeNode(s[sj])
        index = dict[s[sj]]
        head.left = self.inPos(n,ni,index-1,s,si,si+index-ni-1,dict)
        head.right = self.inPos(n,index+1,nj,s,si+index-ni,sj-1,dict)
        return head

先序與後續結合

在這裏插入圖片描述

    #前序和後序
    def prePosToTree(self,preOrder,posOrder):
        if preOrder == None or posOrder == None:
            return None
        dict = {}
        for i in range(0,len(posOrder)):
            dict[posOrder[i]] = i
        return self.prePos(preOrder,0,len(preOrder)-1,posOrder,0,len(posOrder)-1,dict)

    def prePos(self,p,pi,pj,s,si,sj,dict):
        head = TreeNode(s[sj])
        sj -= 1
        if pi == pj:
            return head
        pi += 1
        index = dict[p[pi]]
        head.left = self.prePos(p,pi,pi+index-si,s,si,index,dict)
        head.right = self.prePos(p,pi+index-si+1,pj,s,index+1,sj,dict)
        return head

通過先序和中序數組生成後序數組

在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val  = x
        self.left = None
        self.right = None
          
class Solution(object):
    def getPosArray(self,preOrder,inOrder):
        if preOrder == None or inOrder == None:
            return None
        len = len(preOrder)
        pos = [-1]*len
        dict = {}
        for i in range(0,len):
            dict[inOrder[i]] = i
        self.setPos(preOrder,0,len-1,inOrder,0,len-1,pos,len-1,dict)
        return pos
        
    def setPos(self,p,pi,pj,n,ni,nj,s,si,dict):
        if pi > pj:
            return si
        s[si] = p[pi]
        i = dict[p[pi]]
        
        si = self.setPos(p,pj-nj+i+1,pj,n,i+1,nj,s,si,dict)
        return self.setPos(p,pi+1,pi+i-ni,n,ni,i-1,s,si,dict)

統計和生成不同的二叉樹

在這裏插入圖片描述

統計

在這裏插入圖片描述
動態規劃

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def numTrees(self,n):
        if n < 2:
            return 1
        num = [None]*(n+1)
        num[0] = 1
        for i in range(1,n+1):
            for j in range(1,i+1):
                num[i] += num[j-1]*num[i-j]
        return num[n]

生成

在這裏插入圖片描述
在這裏插入圖片描述

    def generate(self,start,end):
        res = []
        if start > end:
            res.append(None)

        head = None
        for i in range(start,end+1):
            head = TreeNode(i)
            lSubs = self.generate(start,i-1)
            rSubs = self.generate(i+1,end)
            for l in lSubs:
                for r in rSubs:
                    head.left = l
                    head.right = r
                    res.append(self.cloneTree(head))

        return res

    def cloneTree(self,head):
        if head == None:
            return None
        res = TreeNode(head.val)
        res.left = self.cloneTree(head.left)
        res.right = self.cloneTree(head.right)
        return res

統計完全二叉樹的節點數

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

class TreeNode(object):
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def nodeNum(self,head):
        if head == None:
            return 0
        return self.bs(head,1,self.mostLeftLevel(head,1))


    def bs(self,node,l,h):
        if l == h:
            return l
        if self.mostLeftLevel(node.right,l+1) == h:
            return (1 << (h-1)) + self.bs(node.right,l+1,h)
        else:
            return (1 << (h-l-1)) + self.bs(node.left,l+1,h)


    def mostLeftLevel(self,node,level):
        while node != None:
            level += 1
            node = node.left
        return level - 1


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章