給定一棵 Binary Tree,要求找出所有從根節點到葉子節點的路徑,並以字符串形式返回,每一條路徑以「->」符號分隔節點。
用遞迴做的話一定會在這個函數下額外包一個 dfs
方法做,因為需要有變數儲存「->」這個文字。
class Solution(object):
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""
out_str = ""
all_out_str = []
def dfs(out_str, all_out_str, root):
if not root:
return
out_str += str(root.val)
if not root.left and not root.right:
all_out_str.append(out_str)
return
out_str += "->"
dfs(out_str, all_out_str, root.left)
dfs(out_str, all_out_str, root.right)
dfs(out_str, all_out_str, root)
return all_out_str
步驟如下:
這題蠻有意思的,會有一個m x n
的網格,其中每個單元格可以具有三個值之一:
0代表沒有橘子;1代表新鮮的橘子;2代表一個腐敗的橘子,
每經過一分鐘,任何與腐爛橘子相鄰的橘子會腐敗,要計算所有橘子腐敗時間要多久,如果最終無發讓所有橘子腐爛的話返回-1
from collections import deque
class Solution(object):
def orangesRotting(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
queue = deque()
fresh_oranges = 0
rows, cols = len(grid), len(grid[0]) # 使用不同的變數保存行數和列數
# Step 1: 初始化,把腐爛橘子的座標加入隊列,並統計新鮮橘子的數量
for y in range(rows):
for x in range(cols):
if grid[y][x] == 2:
queue.append((x, y)) # 將座標作為元組加入隊列
elif grid[y][x] == 1:
fresh_oranges += 1
# 如果沒有新鮮橘子,直接返回 0
if fresh_oranges == 0:
return 0
# Step 2: BFS 開始腐蝕橘子
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] # 上下左右四個方向
step = 0
while queue:
step += 1
for _ in range(len(queue)):
x, y = queue.popleft()
for dx, dy in directions:
nx, ny = x + dx, y + dy
# 使用 cols 和 rows 來檢查範圍,而不是 x 和 y
if 0 <= nx < cols and 0 <= ny < rows and grid[ny][nx] == 1:
grid[ny][nx] = 2 # 新鮮橘子變腐爛
fresh_oranges -= 1
queue.append((nx, ny)) # 將新腐爛的橘子座標加入隊列
# 如果還有新鮮橘子,無法完全腐爛,返回 -1
return step - 1 if fresh_oranges == 0 else -1
這題想超久,主要是對queue還不太熟悉,再多寫幾題關於bfs的題目!
給定一棵二叉樹,想像自己站在二叉樹的右側,返回從右側可以看到的節點值的列表,就是對於每一層,從右邊可以看到的節點應該被加入結果最後返回。
使用bfs解題:
from collections import deque
def rightSideView_bfs(self, root):
if not root:
return []
result = []
queue = deque([root])
while queue:
level_length = len(queue)
# 遍歷當前層的所有節點
for i in range(level_length):
node = queue.popleft()
# 如果是該層的最後一個節點,將它加入結果
if i == level_length - 1:
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
使用dfs解題:
def rightSideView_dfs(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
result = []
def dfs(node, level):
if not node:
return
if level == len(result):
result.append(node.val)
dfs(node.right, level + 1)
dfs(node.left, level + 1)
dfs(root, 0)
return result
題目:有一個帶有四個轉盤的鎖,每個轉盤有 10 個數字,從 '0' 到 '9',轉動每一個轉盤使其向前或向後一位數,每次只能轉動一個轉盤。
鎖的初始組合是 "0000",給定一個目標組合 target
,用最少的步驟將鎖的組合從 "0000" 轉到目標組合,但有一些「死亡組合」deadends
,途中不能經過這些組合。
最終要返回將 "0000" 轉到 target
的最小步數,如果無法達到目標,則返回 -1
。
這題我完全沒有頭緒...只能先抄作業了
思路:
這是一個典型的"最短路徑問題",並且可以將每一個鎖的組合視作一個狀態,由於需要找出最少步數,因此我們可以使用"廣度優先搜索(BFS)",逐層展開最早找到的解即是最短的解。
步驟:
初始化:將初始組合 "0000" 作為起點加入隊列,同時我們使用一個集合來記錄死亡組合(deadends),以便在搜索過程中避開它們。
廣度優先搜索:
每次從隊列中取出當前狀態,將它與 target
進行比較。如果達到目標,則返回當前步數。
對當前鎖的每一位數,嘗試向上或向下轉動,並生成一個新的組合。如果這個組合不在 deadends
中,且還沒被訪問過,將它加入隊列。
結束條件:如果在 BFS 過程中找到 target
,則返回當前步數。如果隊列變空,則返回-1
,表示無法達到 target
。
from collections import deque
class Solution(object):
def openLock(self, deadends, target):
"""
:type deadends: List[str]
:type target: str
:rtype: int
"""
# 將deadends轉為集合,方便快速查找
dead_set = set(deadends)
# 如果初始狀態就在deadends中,直接返回-1
if "0000" in dead_set:
return -1
# 初始化BFS的隊列和已訪問集合
queue = deque([("0000", 0)]) # 初始狀態是"0000",步數為0
visited = set("0000") # 記錄已訪問過的組合,避免重複訪問
while queue:
current, steps = queue.popleft()
# 如果當前組合等於目標組合,返回步數
if current == target:
return steps
# 嘗試對鎖的四個轉盤進行操作
for i in range(4):
# 對第 i 個轉盤,向上轉和向下轉
for direction in [-1, 1]:
# 取出第i位的數字,將其轉為新的數字
new_digit = (int(current[i]) + direction) % 10
# 生成新的組合
new_combination = current[:i] + str(new_digit) + current[i + 1:]
# 如果新組合不在deadends且沒被訪問過,加入隊列
if new_combination not in dead_set and new_combination not in visited:
queue.append((new_combination, steps + 1))
visited.add(new_combination)
# 如果無法達到目標,返回-1
return -1