1. 程式人生 > >LeetCode Medium 222 計算完全二叉樹節點個數 Python

LeetCode Medium 222 計算完全二叉樹節點個數 Python

def countNodes(self, root):
    """
    Disscussion Method
    演算法:遞迴
    思路:
        非常巧妙!
            利用完全二叉樹和滿二叉樹的性質,首先滿二叉樹是完全二叉樹的一種特殊情況,即所有位置的節點都不為
        空,一顆深度為K的滿二叉樹其節點總數為2^(k)-1,這個很好算,聯想二進位制求和1+2+4+8 =15,也就是16-1
        0001+0010+0100 = 0111 = 1000-1
            所以利用滿二叉樹的性質可以很快地用公式將節點數計算出來
            這裡要做的就是如何從一顆完全二叉樹中分離出滿二叉樹來
            如果一顆完全二叉樹的左右子樹高度相等,則左子樹一定是滿二叉樹,
            否則的話,右子樹一定是一顆滿二叉樹
            由此便可以將一顆完全二叉樹拆成兩個部分分別進行求解。並且注意到,這是將一顆完全二叉樹拆解,拆解後
        的左右兩部分,也一定是一顆完全二叉樹(滿二叉樹也是完全二叉樹),所以可以遞迴的進行拆解,即上述拆完一顆
        滿二叉樹下來並計算節點後可以將剩餘的部分遞迴地繼續進行分離滿二叉樹的過程
            所以這裡要先用一個輔助函式計算樹的高度,因為任意時刻拆解下來的樹一定是完全二叉樹所以可以利用完全
        二叉樹的性質進行高度的計算,即其高度一定是左子樹的高度,在getDepth中就可以只遞迴計算root.left,不用
        計算max(left,right)+1
            再一個是注意到完全二叉樹的節點個數的計算其實是2^(k)-1次,而在將一個樹拆分為處滿二叉樹的時候,如下圖,
        從1開始拆除左側的滿二叉樹時,左側滿二叉樹的高度是2,按理說是2^(k)-1,但是還要加上root,也就是1那個節點,
        所以是2^k - 1+ 1= 2^k, 所以遞迴的時候就是2**k + countNodes(theOtherPart)
            1
           / \
          2   3
         / \  /
        4  5 6
    複雜度:
        時間:OlogN2

    """
    if root == None:
        return 0
    leftDepth = getDepth(root.left)
    rightDepth = getDepth(root.right)
    if leftDepth == rightDepth:
        return 2**leftDepth + self.countNodes(root.right)
    else:
        return 2**rightDepth + self.countNodes(root.left)
def getDepth(root):
    if root == None:
        return 0
    return getDepth(root.left)+1