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 個最小的元素。
說明:
你可以假設 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)
注意:這裡列表中不是整數數字而是字元!!