1042. 不鄰接植花
有 N 個花園,按從 1 到 N 標記。在每個花園中,你打算種下四種花之一。
paths[i] = [x, y]
描述了花園 x 到花園 y 的雙向路徑。
另外,沒有花園有 3 條以上的路徑可以進入或者離開。
你需要爲每個花園選擇一種花,使得通過路徑相連的任何兩個花園中的花的種類互不相同。
以數組形式返回選擇的方案作爲答案 answer,其中 answer[i]
爲在第 (i+1)
個花園中種植的花的種類。花的種類用 1, 2, 3, 4
表示。保證存在答案。
示例 1:
輸入:N = 3, paths = [[1,2],[2,3],[3,1]]
輸出:[1,2,3]
示例 2:
輸入:N = 4, paths = [[1,2],[3,4]]
輸出:[1,2,1,2]
示例 3:
輸入:N = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]]
輸出:[1,2,3,4]
處。
解題思路: 鄰接矩陣(adjacency matrix)是圖ADT最基本的實現方式
代碼如下:
class Solution(object):
def gardenNoAdj(self, N, paths):
"""
:type N: int
:type paths: List[List[int]]
:rtype: List[int]
"""
# 思路: 對於當前的某一個花園,剔除掉與它鄰接花園的花的種類,從剩下的種類中選一種即可。
# 1. 構建鄰接矩陣G; 2. 用res列表保存當前花園花的種類
res = [0]*N
G = [[] for _ in range(N)]
for x, y in paths:
G[x - 1].append(y - 1)
G[y - 1].append(x - 1)
for i in range(N):
# 對於當前花園, 排除掉鄰接的花園的花種就ok了,然後pop出一種
res[i] = ({1,2,3,4} - {res[j] for j in G[i]}).pop()
return res
思路:
- 首先用鄰接表path_map構建地圖,這裏採用的是列表中的下表表示花園,列表中的元素還是列表,表示和這個列表相連接的花園。
- result存放結果,下標是花園,值是花的種類。
- 從花園1開始爲每個花園種花,在當前花園i中,與它相鄰的花園中編號i大的先不用管,該花園還沒有種花;對於編號比i小的花園,需要將他們中的花的種類放到set中,因爲與i相連的花園可能種相同的花。
- 最後從1到4開始遍歷,最小的數字j不在set中,那麼花園i就中花j。
代碼如下:
class Solution:
def gardenNoAdj(self, N: int, paths: List[List[int]]) -> List[int]:
result = [0 for x in range(N+1)]
path_map = [[] for x in range(N+1)]
#構建地圖
for num in paths:
path_map[num[0]].append(num[1])
path_map[num[1]].append(num[0])
s = set() #存儲該花園相鄰的花園種植的花
for i in range(1,N+1):
s.clear()
for j in path_map[i]:
if( j < i):
s.add(result[j])
for j in range(1,5):
if(j not in s):
count = j
break
result[i] = count
return result[1:]
1043. 分隔數組以得到最大和
給出整數數組 A,將該數組分隔爲長度最多爲 K 的幾個(連續)子數組。分隔完成後,每個子數組的中的值都會變爲該子數組中的最大值。
返回給定數組完成分隔後的最大和。
示例:
輸入:A = [1,15,7,9,2,5,10], K = 3
輸出:84
解釋:A 變爲 [15,15,15,9,10,10,10]
動態規劃:
class Solution(object):
def maxSumAfterPartitioning(self, A, K):
"""
:type A: List[int]
:type K: int
:rtype: int
"""
n = len(A)
curmax = 0
res = [0 for _ in range(n)]
for i in range(len(A)):
if i < K:
curmax = max(A[i], curmax)
res[i] = curmax*(i+1)
else:
curmax = 0
for j in range(1, K+1):
curmax = max(A[i-j+1], curmax)
res[i] = max(res[i], res[i-j]+curmax*j)
return res[n-1]
997. 找到小鎮的法官
在一個小鎮裏,按從 1 到 N 標記了 N 個人。傳言稱,這些人中有一個是小鎮上的祕密法官。
如果小鎮的法官真的存在,那麼:
- 小鎮的法官不相信任何人。
- 每個人(除了小鎮法官外)都信任小鎮的法官。
- 只有一個人同時滿足屬性 1 和屬性 2 。
給定數組 trust
,該數組由信任對 trust[i] = [a, b]
組成,表示標記爲 a 的人信任標記爲 b 的人。
如果小鎮存在祕密法官並且可以確定他的身份,請返回該法官的標記。否則,返回 -1。
示例 1:
輸入:N = 2, trust = [[1,2]]
輸出:2
示例 2:
輸入:N = 3, trust = [[1,3],[2,3]]
輸出:3
示例 3:
輸入:N = 3, trust = [[1,3],[2,3],[3,1]]
輸出:-1
示例 4:
輸入:N = 3, trust = [[1,2],[2,3]]
輸出:-1
示例 5:
輸入:N = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
輸出:3
解題思路:
- 分別用兩個數組存儲,一個用來存儲入度數,也就是相信你的人的個數,數組下標就是代表該人,1到N
- 另外一個用來存儲出度數,也就是你相信的人的個數
- 入度數等於N-1,出度數爲0,則這個人就是法官,否則無法確定法官。
class Solution(object):
def findJudge(self, N, trust):
"""
:type N: int
:type trust: List[List[int]]
:rtype: int
"""
a=[0 for x in range(N+1)] #相信你的人
b=[0 for x in range(N+1)] #你相信的人
for num in trust:
a[num[1]]+=1 #儲存爲相信他的人
b[num[0]] +=1
for i ,num in enumerate(a):
if(i!=0 and num==N-1):
if b[i]==0:
return i
return -1
841. 鑰匙和房間
有 N 個房間,開始時你位於 0 號房間。每個房間有不同的號碼:0,1,2,…,N-1,並且房間裏可能有一些鑰匙能使你進入下一個房間。
在形式上,對於每個房間 i 都有一個鑰匙列表 rooms[i]
,每個鑰匙 rooms[i][j]
由 [0,1,...,N-1]
中的一個整數表示,其中 N = rooms.length
。 鑰匙 rooms[i][j] = v
可以打開編號爲 v 的房間。
最初,除 0 號房間外的其餘所有房間都被鎖住。
你可以自由地在房間之間來回走動。
如果能進入每個房間返回 true,否則返回 false。
示例 1:
輸入: [[1],[2],[3],[]]
輸出: true
解釋:
我們從 0 號房間開始,拿到鑰匙 1。
之後我們去 1 號房間,拿到鑰匙 2。
然後我們去 2 號房間,拿到鑰匙 3。
最後我們去了 3 號房間。
由於我們能夠進入每個房間,我們返回 true。
示例 2:
輸入:[[1,3],[3,0,1],[2],[0]]
輸出:false
解釋:我們不能進入 2 號房間。
解題思路:
有向圖的深度優先搜索。
設置兩個數組notVisited
、visited,
分別存放還未遍歷過的房間號和已經遍歷過的房間號。如果notVisited
數組爲空說明我們已經遍歷過所有房間,直接返回,如果當前房間已經遍歷過了也直接返回。然後遍歷鑰匙串中的房間號。
代碼如下:
代碼如下:
class Solution(object):
def canVisitAllRooms(self, rooms):
"""
:type rooms: List[List[int]]
:rtype: bool
"""
notVisited = [i for i in range(1, len(rooms))]
visited = []
def dfs(curRoom, keys):
if len(notVisited) == 0:
return
if curRoom in visited:
return
visited.append(curRoom)
for key in keys:
if key in notVisited:
notVisited.remove(key)
dfs(key, rooms[key])
dfs(0, rooms[0])
return True if len(notVisited) == 0 else False
802. 找到最終的安全狀態
思路分析:典型的圖深度優先搜索。
dfs訪問圖,當前訪問路徑上節點狀態待定,爲-1:
- 訪問完當前路徑,未發現環,則所有節點狀態標記爲1(已訪問節點)。
- 發現環,所有節點狀態不變,爲-1(環上節點)。
class Solution(object):
def eventualSafeNodes(self, graph):
"""
:type graph: List[List[int]]
:rtype: List[int]
"""
nodes_status = [0] * len(graph)
safe_nodes = []
for i in range(len(graph)):
if nodes_status[i] == 0:
self.dfs(graph, i, nodes_status, safe_nodes)
return sorted(safe_nodes)
def dfs(self, graph, i, nodes_status, safe_nodes):
nodes_status[i] = 1
flag = False
for sub_node in graph[i]:
if nodes_status[sub_node] == 0:
if self.dfs(graph, sub_node, nodes_status, safe_nodes):
flag = True
elif nodes_status[sub_node] == 1:
flag = True
if not flag:
safe_nodes.append(i)
nodes_status[i] = 2
return flag
332. 重新安排行程
class Solution(object):
def findItinerary(self, tickets):
"""
:type tickets: List[List[str]]
:rtype: List[str]
"""
tickets.sort()
hel = [False for i in range(len(tickets))]
def dfs(s,res):
if len(res)==len(tickets)+1:
return res
for i in range(len(tickets)):
if not hel[i] and tickets[i][0]==s:
hel[i] = True
r = dfs(tickets[i][1],res+[tickets[i][1]])
if not r:
hel[i] = False
else:return r
return dfs('JFK',['JFK'])