1. 程式人生 > >玩轉演算法面試LeetCode演算法練習——二叉樹與遞迴

玩轉演算法面試LeetCode演算法練習——二叉樹與遞迴

目錄

104. 二叉樹的最大深度

給定一個二叉樹,找出其最大深度。

二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定二叉樹 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

# 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):
        """
        :type root: TreeNode
        :rtype: int
        """
        if root == None:
            return 0
        leftDepth = self.maxDepth(root.left) + 1
        rightDepth = self.maxDepth(root.right) + 1
        return max(leftDepth,rightDepth)

111. 二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

說明: 葉子節點是指沒有子節點的節點。

示例:

給定二叉樹 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最小深度  2.

思路:

如果根節點為空,那麼返回0,如果左子樹為空,返回右子樹的最低高度+1,右子樹為空,返回左子樹最低高度+1,否則返回min(左子樹最低高度,右子樹最低高度)+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 minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        
        """     
        if not root:
            return 0
        if not root.right:
            return self.minDepth(root.left)+1
        elif not root.left:
            return self.minDepth(root.right)+1
        else:
            return min( self.minDepth( root.left ), self.minDepth( root.right ) ) + 1

 226. 翻轉二叉樹

翻轉一棵二叉樹。

示例:

輸入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

輸出:

     4
   /   \
  7     2
 / \   / \
9   6 3   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 invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root == None:
            return None
        self.invertTree(root.left)
        self.invertTree(root.right)        
        root.left, root.right = root.right, root.left
        return root

 100. 相同的樹

給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。

如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。

示例 1:

輸入:       1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

輸出: true

示例 2:

輸入:      1          1
          /           \
         2             2

        [1,2],     [1,null,2]

輸出: false

示例 3:

輸入:       1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

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

class Solution:
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        if not p and not q:#遞迴邊界
            return True
        if p and q and p.val == q.val:
            return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
        else:
            return False

101. 對稱二叉樹

給定一個二叉樹,檢查它是否是映象對稱的。

例如,二叉樹 [1,2,2,3,4,4,3] 是對稱的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面這個 [1,2,2,null,3,null,3] 則不是映象對稱的:

    1
   / \
  2   2
   \   \
   3    3

思路主要參考leetcode100題,這裡將根節點的左右節點假設成兩顆獨立的樹,這樣解題跟100就是類似的了,區別:遞迴呼叫時,因是對稱,所以是左樹左節點與右樹右節點,左樹右節點與右樹左節點

# 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):
        """
        :type root: TreeNode
        :rtype: bool
        
        """
        def isSameTree(p,q):
            if not p and not q:
                return True
            if p and q and p.val == q.val:
                #因是對稱,所以是左樹左節點與右樹右節點,左樹右節點與右樹左節點
                return isSameTree(p.left,q.right) and isSameTree(p.right,q.left)
            else:
                return False
        
        if not root:
            return True
        else:
            return isSameTree(root.left,root.right)

 222. 完全二叉樹的節點個數

給出一個完全二叉樹,求出該樹的節點個數。

說明:

完全二叉樹的定義如下:在完全二叉樹中,除了最底層節點可能沒填滿外,其餘每層節點數都達到最大值,並且最下面一層的節點都集中在該層最左邊的若干位置。若最底層為第 h 層,則該層包含 1~ 2h 個節點。

示例:

輸入: 
    1
   / \
  2   3
 / \  /
4  5 6

輸出: 6

思想是

計算樹的高度,判斷是否為滿二叉樹,YES則 節點個數=2^(height)-1。NO,遞迴判斷左右子樹是否為滿二叉樹,利用公式把節點計算出來。

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

class Solution:
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """      
        if not root:
            return 0
        hl = hr = 0
        l = r = root
        while l:
            hl += 1
            l = l.left
        while r:
            hr += 1
            r = r.right
        if hl == hr:#相等為滿二叉樹
            return 2 ** hl - 1
        else:
            return 1 + self.countNodes(root.left) + self.countNodes(root.right)

110. 平衡二叉樹 

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

本題中,一棵高度平衡二叉樹定義為:

一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。

示例 1:

給定二叉樹 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回 true

示例 2:

給定二叉樹 [1,2,2,3,3,null,null,4,4]

       1
      / \
     2   2
    / \
   3   3
  / \
 4   4

返回 false

思路:獲取當前節點的左右子數深度,絕對值差大於1,return False,小於1則依次遞迴左右子節點的左右子樹(每個左右子樹都可以想成獨立的二叉樹),只有左右子樹都為True,才為True

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

class Solution:
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        lDepth = self.getDepth(root.left)
        rDepth = self.getDepth(root.right)
        if abs(lDepth-rDepth) > 1:
            return False
        else:
            return self.isBalanced(root.left) and self.isBalanced(root.right)
        
    def getDepth(self , root):
        if root == None:
            return 0;
        lDepth = self.getDepth(root.left);
        rDepth = self.getDepth(root.right);
        return max(lDepth , rDepth) + 1;

112. 路徑總和

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。

說明: 葉子節點是指沒有子節點的節點。

示例: 
給定如下二叉樹,以及目標和 sum = 22

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1

返回 true, 因為存在目標和為 22 的根節點到葉子節點的路徑 5->4->11->2

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

class Solution:
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if root is None:
            return False
        if root.left is None and root.right is None:
            return sum == root.val
        return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right,sum-root.val)

404. 左葉子之和

計算給定二叉樹的所有左葉子之和。

示例:

    3
   / \
  9  20
    /  \
   15   7

在這個二叉樹中,有兩個左葉子,分別是 9 和 15,所以返回 24
# 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):
        """
        :type root: TreeNode
        :rtype: int
        """
        sum = 0
        if root == None:
            return 0
        if root.left and root.left.left ==None and root.left.right == None:
            sum =root.left.val
            
        return sum + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)

257. 二叉樹的所有路徑

給定一個二叉樹,返回所有從根節點到葉子節點的路徑。

說明: 葉子節點是指沒有子節點的節點。

示例:

輸入:

   1
 /   \
2     3
 \
  5

輸出: ["1->2->5", "1->3"]

解釋: 所有根節點到葉子節點的路徑為: 1->2->5, 1->3

遞迴:

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

class Solution:
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        if root == None:
            return []
        res = []
        if root.left == None and root.right == None:
            res.append(str(root.val))
            return res
        leftS = self.binaryTreePaths(root.left)
        for i in range(len(leftS)):
            res.append(str(root.val)+'->'+leftS[i])
        rightS = self.binaryTreePaths(root.right)
        for i in range(len(rightS)):
            res.append(str(root.val)+'->'+rightS[i])
            
        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 binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        if not root:
            return []
        res, stack = [], [(root, "")]
        while stack:
            node, ls = stack.pop()
            if not node.left and not node.right:
                res.append(ls + str(node.val))            
            if node.left:
                stack.append((node.left, ls + str(node.val) + "->"))             
            if node.right:
                stack.append((node.right, ls + str(node.val) + "->"))
                
        return res

 113. 路徑總和 II

給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定如下二叉樹,以及目標和 sum = 22

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def dfs(self, node, target, sum, path):
        if node is None:
            return []
        sum = sum + node.val
        path = path + [node.val]
        if node.left is None and node.right is None:
            if sum == target:
                self.target_paths.append(path)
            return []
        self.dfs(node.left, target, sum, path)
        self.dfs(node.right, target, sum, path)


    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        self.target_paths = []
        self.dfs(root, sum, 0, [])
        return self.target_paths

 129. 求根到葉子節點數字之和

給定一個二叉樹,它的每個結點都存放一個 0-9 的數字,每條從根到葉子節點的路徑都代表一個數字。

例如,從根到葉子節點路徑 1->2->3 代表數字 123

計算從根到葉子節點生成的所有數字之和。

說明: 葉子節點是指沒有子節點的節點。

示例 1:

輸入: [1,2,3]
    1
   / \
  2   3
輸出: 25
解釋:
從根到葉子節點路徑 1->2 代表數字 12.
從根到葉子節點路徑 1->3 代表數字 13.
因此,數字總和 = 12 + 13 = 25.

示例 2:

輸入: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
輸出: 1026
解釋:
從根到葉子節點路徑 4->9->5 代表數字 495.
從根到葉子節點路徑 4->9->1 代表數字 491.
從根到葉子節點路徑 4->0 代表數字 40.
因此,數字總和 = 495 + 491 + 40 = 1026.
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.total = 0
        self.dfs(root,0)
        return self.total
    def dfs(self, node, val):
        if node is None:
            return []
        if node.left is None and node.right is None:
                self.total = self.total + val * 10 + node.val
        self.dfs(node.left,  val * 10 + node.val)
        self.dfs(node.right, val * 10 + node.val)

437. 路徑總和 III

給定一個二叉樹,它的每個結點都存放著一個整數值。

找出路徑和等於給定數值的路徑總數。

路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。

二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。

示例:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

返回 3。和等於 8 的路徑有:

1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11
# 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):
    #在以root為根節點的二叉樹中,尋找和為sum的路徑,返回這樣的路徑個數
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int

        """
        
        if root == None:
            return 0
        res = self.findPath(root,sum)#包含當前根節點的路徑值
        res += self.pathSum(root.left, sum)#不包含當前根節點左右子樹的路徑值
        res += self.pathSum(root.right,sum)
        
        return res
    #在以node為根節點的二叉樹中,尋找包含node的路徑,和為sum
    #返回這樣的路徑個數
    def findPath(self,node,num):
        if node == None:
            return 0
        res = 0
        if node.val == num :
            res += 1
        
        res += self.findPath(node.left,num - node.val)
        res += self.findPath(node.right,num - node.val)
        
        return res