1. 程式人生 > >Leetcode——中級部分——樹和圖部分——Python實現

Leetcode——中級部分——樹和圖部分——Python實現

中序遍歷二叉樹

給定一個二叉樹,返回它的中序 遍歷。

示例:

輸入: [1,null,2,3]
   1
    \
     2
    /
   3

輸出: [1,3,2]

進階: 遞迴演算法很簡單,你可以通過迭代演算法完成嗎?

我的解答:

方法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 inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        def recurse(node):
            if node != None:
                recurse(node.left)
                res.append(node.val)
                recurse(node.right)
        recurse(root)
        return res

方法2——迭代實現(主要會用到資料結構 stack):

class Solution:
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        stack = []
        result = []
        node = root
        while node or (len(stack) > 0):
            if node != None:
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                result.append(node.val)
                node = node.right
        return result

二叉樹的鋸齒形層次遍歷

給定一個二叉樹,返回其節點值的鋸齒形層次遍歷。(即先從左往右,再從右往左進行下一層遍歷,以此類推,層與層之間交替進行)。

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

    3
   / \
  9  20
    /  \
   15   7

返回鋸齒形層次遍歷如下:

[
  [3],
  [20,9],
  [15,7]
]

我的解答:

層次遍歷採用佇列實現。
相比於標準層次遍歷,這裡只是在result中加入templist時加了一步判斷flag是否為負的步驟,如果為負,表示是偶數次遍歷應該從右往左,將templist更新為逆序

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

class Solution:
    def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root == None:
            return []
        
        result = []
        queue = [root]
        flag = 1
        while queue:
            length = len(queue)
            tempList = []
            #下面是一層的結點的遍歷
            for i in range(length):
                node = queue.pop(0)
                tempList.append(node.val)
                if node.left != None:
                    queue.append(node.left)
                if node.right != None:
                    queue.append(node.right)
            #判斷是否為偶數層(flag),如果是就需要逆序tempList
            if flag == -1:
                tempList = tempList[::-1]
            result.append(tempList)
            flag = flag * (-1)
        return result

從前序與中序遍歷序列構造二叉樹

根據一棵樹的前序遍歷與中序遍歷構造二叉樹。

注意:
你可以假設樹中沒有重複的元素。

例如,給出

前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]

返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

我的解答:

前序遍歷先訪問根節點,因此前序遍歷序列的第一個字母肯定就是根節點,即A是根節點;然後,由於中序遍歷先訪問左子樹,再訪問根節點,最後訪問右子樹,所以我們找到中序遍歷中A的位置,然後A左邊的字母就是左子樹了,也就是CBD是根節點的左子樹;同樣的,得到EF為根節點的右子樹。將前序遍歷序列分成BCD和EF,分別對左子樹和右子樹應用同樣的方法,遞迴下去,二叉樹就成功構建好了。

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

class Solution:
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if preorder == []:
            return None
        root = TreeNode(preorder[0]) #構建一個樹物件
        i = inorder.index(root.val) #在中序遍歷序列中找到根節點索引
        root.left = self.buildTree(preorder[1:1+i],inorder[:i])
        root.right = self.buildTree(preorder[1+i:],inorder[i+1:])
        return root

每個節點的右向指標

給定一個二叉樹

struct TreeLinkNode {
  TreeLinkNode *left;
  TreeLinkNode *right;
  TreeLinkNode *next;
}

填充它的每個 next 指標,讓這個指標指向其下一個右側節點。如果找不到下一個右側節點,則將 next 指標設定為 NULL

初始狀態下,所有 next 指標都被設定為 NULL

說明:

  • 你只能使用額外常數空間。
  • 使用遞迴解題也符合要求,本題中遞迴程式佔用的棧空間不算做額外的空間複雜度。
  • 你可以假設它是一個完美二叉樹(即所有葉子節點都在同一層,每個父節點都有兩個子節點)。

示例:

給定完美二叉樹,

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

呼叫你的函式後,該完美二叉樹變為:

     1 -> NULL
   /  \
  2 -> 3 -> NULL
 / \  / \
4->5->6->7 -> NULL

我的解答:

採用BFS遍歷(層次遍歷),每一層遍歷後,遍歷節點列表,列表中前一節點next指標指向後一節點。

# Definition for binary tree with next pointer.
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None

class Solution:
    # @param root, a tree link node
    # @return nothing
    def connect(self, root):
        node = [root]
        while node:
            temp = []
            for i in node:
                if i != None:
                    if i.left != None:
                        temp.append(i.left)
                    if i.right != None:
                        temp.append(i.right)
            for index,nodeValue in enumerate(node[:-1]):
                nodeValue.next = node[index+1]
            node = temp

二叉搜尋樹中第K小的元素

給定一個二叉搜尋樹,編寫一個函式 kthSmallest 來查詢其中第 個最小的元素。

說明:
你可以假設 k 總是有效的,1 ≤ k ≤ 二叉搜尋樹元素個數。

示例 1:

輸入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
輸出: 1

示例 2:

輸入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
輸出: 3

進階:
如果二叉搜尋樹經常被修改(插入/刪除操作)並且你需要頻繁地查詢第 k 小的值,你將如何優化 kthSmallest 函式?

我的解答:

層次遍歷得到二叉搜尋樹每一個元素,進行排序(list的sort函式),返回第k小元素。

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

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        #下面是層次遍歷過程
        queue = [root]
        lyst = []
        while queue:
            node = queue.pop(0)
            lyst.append(node.val) #list儲存每一個元素
            if node.left != None:
                queue.append(node.left)
            if node.right != None:
                queue.append(node.right)
        #下面是排序過程
        lyst.sort()
        #下面是返回第k小元素過程
        return lyst[k-1]

島嶼的個數

給定一個由 '1'(陸地)和 '0'(水)組成的的二維網格,計算島嶼的數量。一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連線而成的。你可以假設網格的四個邊均被水包圍。

示例 1:

輸入:
11110
11010
11000
00000

輸出: 1

示例 2:

輸入:
11000
11000
00100
00011

輸出: 3

我的解答:

我們遍歷矩陣的每一個點,對每個點都嘗試進行一次深度優先搜尋,如果搜尋到1,就繼續向它的四周搜尋。同時我們每找到一個1,就將其標為0,這樣就能把整個島嶼變成0。我們只要記錄對矩陣遍歷時能進入多少次搜尋,就代表有多少個島嶼。

class Solution:
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        #注意:這個題目裡面每個數字都是字元!!!
        row = len(grid)
        if row == 0:
            return 0
        column = len(grid[0])
        if column == 0:
            return 0
        res = 0
        for i in range(row):
            for j in range(column):
                if grid[i][j] == '1':
                    res = res + 1 #島嶼數+1
                    self.DFS(grid,i,j) #保證這個島嶼所有連線的位置都置零
        return res
        
    #深度優先遍歷(所有相連島嶼置零操作)    
    def DFS(self,grid,i,j):
        #注意:這裡需要一個判斷是否溢位邊界的條件
        if i<0 or j<0 or i>=len(grid) or j>=len(grid[0]):
            return
        if grid[i][j] == '1':
            grid[i][j] = '0'
            self.DFS(grid,i-1,j)
            self.DFS(grid,i+1,j)
            self.DFS(grid,i,j-1)
            self.DFS(grid,i,j+1)

注意:這裡列表中不是整數數字而是字元!!