记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
使用node记录所有成对出现过的数a,b = value
并用weight记录这一对数的值 weight[(a,b)] = value weight[(b,a)] = 1/value
然后对queries内的每一对(x,y)进行dfs:
如果(x,y)已经存在weight中 直接返回值
如果x或者y没有在node中 说明这个未知数没有出现过 直接返回0
如果start已经出现过了 也直接返回0
将这个start加入到visited中
然后遍历与start成对出现过的数node[start]
weight[(start,v)] * dfs(v,end,visited) 及 start到end的值
如果这个值不为零 说明找到了 并将这一对加入到weight 方便以后查询
def calcEquation(equations, values, queries):
"""
:type equations: List[List[str]]
:type values: List[float]
:type queries: List[List[str]]
:rtype: List[float]
"""
from collections import defaultdict
node = defaultdict(set)
weight = defaultdict()
ret = []
for i in range(len(equations)):
x,y = equations[i]
node[x].add(y)
node[y].add(x)
weight[(x,y)] = values[i]
weight[(y,x)] = 1.0 / values[i]
def dfs(start,end,visited):
if (start,end) in weight:
return weight[(start,end)]
if start not in node or end not in node:
return 0
if start in visited:
return 0
visited.add(start)
ans=0
for v in node[start]:
ans = weight[(start,v)] * dfs(v,end,visited)
if ans!=0:
weight[(start,end)] = ans
break
visited.remove(start)
return ans
for x,y in queries:
res = dfs(x,y,set())
if res==0:
ret.append(-1.0)
else:
ret.append(res)
return ret
visit记录已加入朋友圈的人
topv记录他的朋友已经都被加入朋友圈 省去重复判断
依次遍历每一个人 若这个人没有加入朋友圈 则新建一个朋友圈
并通过dfs寻找他的所有朋友加入朋友圈
而这个人的朋友都已加入 所以他会被加入到topv中
dfs:
如果node已加入topv说明这个人所有朋友圈已经被考虑 跳过
否则遍历node的所有未加入visited的朋友 加入朋友圈 并dfs这个朋友
def findCircleNum(M):
"""
:type M: List[List[int]]
:rtype: int
"""
visited=set()
topv = set()
ans = 0
def dfs(node):
if node in topv:
return
for i in range(len(M)):
if i in visited:
continue
if M[node][i]==1:
visited.add(i)
dfs(i)
for i in range(len(M)):
if i not in visited:
print(i)
ans+=1
dfs(i)
topv.add(i)
return ans
[a,b]使用end记录节点的连接点 while递归找到终结点 若两个点的终结点不同
说明a,b这条线段连接了两个不同的区域 是必须的
若相同 则说明没有ab也已经连通 ab属于可以去除的线段
def findRedundantConnection(edges):
"""
:type edges: List[List[int]]
:rtype: List[int]
"""
end={}
res = ""
for x,y in edges:
end[x]=x
end[y]=y
for tmp in edges:
x = tmp[0]
y = tmp[1]
while x != end[x]:
x = end[x]
while y != end[y]:
y = end[y]
if x==y:
res = tmp
else:
end[x] = y
return res
根据题目意思 只要两个账号中包含相同的邮箱地址 则认为两个账号可以合并
使用并查集
对每个邮箱创建一个终点邮箱
mailPos: {email:账号位置} 记录所有邮箱对应的账号位置 出现多次对应哪个位置都可以 因为认定为一个账号
rootSet: 存储每个邮箱的终点邮箱 若终点邮箱相同 则代表两个邮箱在同一个账号中
find:
寻找邮箱i的终点邮箱 并返回
union:
寻找邮箱i,j的终点邮箱
若不同
则将i的终点变为j的终点 及将i,j变为同一个账号
遍历已有的账号
将一个账号内的邮箱合并 这里和第一个邮箱合并
结果生成:
遍历所有存在的邮箱
找到其终点邮箱 dic内key为终点邮箱的账号位置 将这个邮箱加入其中
最后加入账号位置上的账号名称
def accountsMerge(accounts):
"""
:type accounts: List[List[str]]
:rtype: List[List[str]]
"""
from collections import defaultdict
mailPos = {mail:pos for pos,account in enumerate(accounts) for mail in account[1:]}
rootSet = {mail:mail for mail in mailPos}
def find(i):
while rootSet[i]!=i:
rootSet[i] = rootSet[rootSet[i]]
i = rootSet[i]
return i
def union(i,j):
if i!=j:
endi = find(i)
endj = find(j)
if endi!=endj:
rootSet[endi] = rootSet[j]
for account in accounts:
l = len(account)
for i in range(1,l):
email = account[i]
union(email,find(account[1]))
dic = defaultdict(set)
for mail in rootSet:
pos = mailPos[find(mail)]
dic[pos].add(mail)
ans = [[accounts[pos][0]]+sorted(mail) for pos,mail in dic.items()]
return ans
难点:读懂题目 第一次看的中文 没看清楚 以为是去除一行或一列…
a move consists of removing a stone that shares a column or row with another stone on the grid.
题目的意思是move操作可以移除一个石头(这个石头的同行或者同列存在其他石头)
所以可以用并查集
将存在于一列或者一样的石子归并到一类 有同样的root石子
同样的find union
最终 每一类n个石子中可以移除n-1个 必定到最后只剩一个没法移除
所以可以移除的最大个数 = 所有个数len(stones) - 所有的类别数len(ret)
def removeStonesError(stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
from collections import defaultdict
row = defaultdict(set)
col = defaultdict(set)
rownum = defaultdict(int)
colnum = defaultdict(int)
for stone in stones:
pos=(stone[0],stone[1])
row[stone[0]].add(pos)
col[stone[1]].add(pos)
rownum[stone[0]]+=1
colnum[stone[1]]+=1
count=0
while len(stones)>0:
print("rn:",rownum)
print("cn:",colnum)
minrow = min(rownum,key = rownum.get)
mincol = min(colnum,key = colnum.get)
count+=1
if rownum[minrow]<colnum[mincol]:
tmp = row.pop(minrow)
rownum.pop(minrow)
for x,y in tmp:
pos = (x,y)
print(pos)
stones.remove([x,y])
col[y].remove(pos)
colnum[y]-=1
if colnum[y]==0:
colnum.pop(y)
else:
tmp = col.pop(mincol)
colnum.pop(mincol)
for x,y in tmp:
pos = (x,y)
print(pos)
stones.remove([x,y])
row[x].remove(pos)
rownum[x]-=1
if rownum[x]==0:
rownum.pop(x)
print(count)
return count
def removeStones(stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
from collections import defaultdict
row = defaultdict(set)
col = defaultdict(set)
root = {}
def find(i):
while root[i]!=i:
root[i] = root[root[i]]
i = root[i]
return i
def union(i,j):
if i!=j:
endi = find(i)
endj = find(j)
if endi!=endj:
root[endi] = root[j]
for x,y in stones:
root[(x,y)] = (x,y)
row[x].add((x,y))
col[y].add((x,y))
for x,y in stones:
pos = (x,y)
for i in row[x]:
union(i,pos)
for j in col[y]:
union(j,pos)
ret = {find((x,y)) for x,y in stones}
ans =len(stones)-len(ret)
return ans