1557. Minimum Number of Vertices to Reach All Nodes
class Solution:
def findSmallestSetOfVertices(self, n: int, edges: List[List[int]]) -> List[int]:
# union find or node with no-indegree
re = set(range(n))
for a, b in edges:
if b in re:
re.remove(b)
return list(re)
# parent = [i for i in range(n)]
# def find(a):
# if parent[a] != a:
# return find(parent[a])
# return a
# def union(a, b):
# pa = find(a)
# parent[b] = pa
# for a, b in edges: # a -> b
# union(a, b)
# unique_p = set(parent)
# re = set()
# for p in parent:
# re.add(find(p))
# return list(re)
399. Evaluate Division
class Solution(object):
def calcEquation(self, equations, values, queries):
graph = collections.defaultdict(set)
for i, vertices in enumerate(equations):
v1, v2 = vertices
value = values[i]
graph[v1].add((v2, value))
graph[v2].add((v1, 1/value))
def find_path(v1, v2):
if v1 not in graph or v2 not in graph:
return -1
q = []
q.append([v1, 1])
visited = set()
while q:
front, product = q.pop(0)
if front == v2:
return product
visited.add(front)
for neighbor, value in graph[front]:
if neighbor not in visited:
q.append([neighbor, product*value])
return -1
return [find_path(v1, v2) for v1, v2 in queries]
935. Knight Dialer
转换成可以有几条路径来跳N次
class Solution(object):
def knightDialer(self, N):
graph = [[4, 6], [6, 8], [7, 9], [4, 8], [0, 3, 9], [], [0, 1, 7], [2, 6], [1, 3], [2, 4]]
memo = collections.defaultdict(dict)
MOD = 1000000007
def helper(n, curNum, memo): # 计算单个数字curNum 跳N次,有几条路径
if n == 0:
return 1
if memo[n].get(curNum) is not None:
return memo[n][curNum]
count = 0
for neig in graph[curNum]:
count += helper(n-1, neig, memo) % MOD
memo[n][curNum] = count
return count
res = 0
for i in xrange(10):
res += helper(N-1, i, memo) % MOD
return res % MOD
688. Knight Probability in Chessboard
下面这个超时, 因为会有重复的,比如都是第10步走到X,Y这个地方,后面还有5步要走。后面的5步就不需要重复的遍历。
# 每一步的概率都是上一步的概率除以8,累加所有路径可以走K步的
class Solution(object):
def knightProbability(self, N, K, r, c):
moves = ((-1, -2), (-2, -1), (-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (1, -2))
re = 0
q = [(r, c, K, 1)]
while q:
x, y, k, p = q.pop(0)
if 0 <= x < N and 0 <= y < N :
if k > 0:
k -= 1
for i, j in moves:
q.append([x+i, y+j, k, p / 8.0])
elif k == 0:
re += p
return re
改进:
class Solution(object):
def knightProbability(self, N, K, r, c):
moves = ((-1, -2), (-2, -1), (-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (1, -2))
memo = {}
def dfs(x, y, k, p):
if k == 0:
return p
if (x, y, k) in memo:
return memo[(x, y, k)]
sum_p = 0
for dx, dy in moves:
i, j = x+dx, y+dy
if 0 <= i < N and 0 <= j < N:
sum_p += dfs(i, j, k-1, p/8.0)
memo[(x, y, k)] = sum_p
return sum_p
return dfs(r, c, K, 1)
310. Minimum Height Trees
思路: 最短的MHT的root是最长的路径的中间节点。所以最多只会有2个root。计算所有点的入度,每次去掉入度为1的节点。对应的邻居就要入度-1.再次重复步骤去掉入度为1的节点,直到剩下小于2个点。
class Solution(object):
def findMinHeightTrees(self, n, edges):
if n == 1: return [0]
neighbors = collections.defaultdict(list)
degress = collections.defaultdict(int)
for u,v in edges:
neighbors[u].append(v)
neighbors[v].append(u)
degress[u] += 1
degress[v] += 1
level = []
for i in xrange(n): # 找到入度为1的
if degress[i] == 1:
level.append(i)
unvisited = set(range(n))
while len(unvisited) > 2: # 这里是unvisited >2 不是len(level)
nextLevel = []
for u in level:
unvisited.remove(u)
for neighbor in neighbors[u]:
if neighbor in unvisited:
degress[neighbor] -= 1
if degress[neighbor] == 1:
nextLevel.append(neighbor)
level = nextLevel
return level