Biweekly Contest 91
Biweekly Contest 91
Problem A
Number of Distinct Averages
思路
按照题意模拟即可,最后set的大小就是所求结果
代码
class Solution:
def distinctAverages(self, nums: List[int]) -> int:
nums.sort()
s =set()
n = len(nums)
for i in range(n//2):
s.add(nums[i]+nums[n-i-1])
return len(s)
Problem B
Count Ways To Build Good Strings
思路
比赛时想偏了,一直以为是组合数推公式,后面才反应过来是DP题。最开始的想法自然是0,1分开处理,反正开个2维内存也不会很大。第一维是长度,第二维是0、1,后面转移方程感觉有点问题,但是所幸过了。后面看了大佬的题解才搞明白正确的转移方程,而且0、1是可以合并的,不会干扰到计算。
代码
比赛代码
import numpy as np
class Solution:
def countGoodStrings(self, low: int, high: int, zero: int, one: int) -> int:
ans = 0
MOD = int(1e9+7)
# print(MOD)
dp = np.zeros((high+1,2),dtype = np.int)
dp[zero][0] = 1
dp[one][1] = 1
for i in range(high+1):
# print(i)
if i-zero>=0:
dp[i][0] = max(dp[i][0],dp[i-zero][0]+dp[i-zero][1])%MOD
if i - one>=0:
dp[i][1] = max(dp[i][1],dp[i-one][0]+dp[i-one][1])%MOD
# print(dp)
ans = 0
for i in range(low,high+1):
ans = (ans+dp[i][0]+dp[i][1])%MOD
return ans
补题代码
class Solution:
def countGoodStrings(self, low: int, high: int, zero: int, one: int) -> int:
MOD = 10**9+7
dp = [1]+[0]*(high)
for i in range(high+1):
if i>=one: dp[i] = (dp[i]+dp[i-one])%MOD
if i>=zero: dp[i] = (dp[i]+dp[i-zero])%MOD
return sum(dp[low:])%MOD
Problem C
Most Profitable Path in a Tree
思路
思路不难,bob找0的路径是固定的,先1遍DFS求这个,然后从0开始dfs,找一个最小代价的到叶节点的路径就好了,代价计算就按照题目要求来写,我比赛的时候是对遍建的邻接表,感觉建树会好处理一点。这题蛮可惜的,B题花了太多时间,赛后才过。大佬的想法跟我差不多,优化的点一个是用fa保证不会重复访问,这是树的特点,我用的是visit数组,还有就是相遇节点如何判定,大佬用的是一个时间数组,而我因为用的是visit数组,导致判定比较复杂,也出了不少BUG.
代码
比赛代码
import numpy as np
class Solution:
def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
n = len(edges)
G = []
for i in range(n+1):
G.append([])
for i in range(n):
x,y,c = edges[i][0],edges[i][1],amount[i]
# print(x,y,c)
G[x].append(y)
G[y].append(x)
B = []
# print(G)
visit = np.zeros(n+1,dtype= np.int)
def getSite(x):
if x == 0:
B.append(x)
return True
for item in G[x]:
if visit[item]==0:
visit[item]=1
if getSite(item):
# print(B)
B.append(x)
return True
visit[item] = 0
return False
visit[bob] =1
getSite(bob)
B = B[::-1]
# print(B)
self.t = len(B)
self.ans = "S"
visit = np.zeros(n+1,dtype= np.int)
visit1 = np.zeros(n+1,dtype= np.int)
def dfs(x,v,d):
# print(x,v,d)
if x!=0 and len(G[x])==1:
if self.ans == "S":
self.ans = v
else:
self.ans= max(self.ans,v)
return
if d+1<self.t:
visit1[B[d+1]] = 1
for item in G[x]:
# print(x,item)
c = amount[item]
if visit[item]==0:
visit[item] = 1
if d+1<self.t and item == B[d+1]:
dfs(item,v+c//2,d+1)
continue
if visit1[item]==0:
dfs(item,v+c,d+1)
else:
dfs(item,v,d+1)
visit[item] = 0
if d+1<self.t:
visit1[B[d+1]] = 0
# print("end",x,visit)
return
c = 0
if B[0]==0:
c = amount[0]//2
else:
c = amount[0]
visit[0] = 1
visit1[bob] = 1
dfs(0,c,0)
return self.ans
补题代码
class Solution:
def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
n = len(amount)+1
G = [[] for _ in range(n)]
for x,y in edges:
G[x].append(y)
G[y].append(x)
bob_time = [n]*n
bob_time[bob] = 0
def dfs_bob(x,fa,t):
if x==0:
return True
for y in G[x]:
if y!=fa:
if dfs_bob(y,x,t+1):
bob_time[y]=t+1
return True
return False
dfs_bob(bob,-1,0)
ans = -inf
def dfs_a(x,fa,t,tot):
if t<bob_time[x]:
tot+=amount[x]
elif t==bob_time[x]:
tot+=amount[x]//2
if x!=0 and len(G[x])==1:
nonlocal ans
ans = max(ans,tot)
return
for y in G[x]:
if y!=fa:
dfs_a(y,x,t+1,tot)
return
dfs_a(0,-1,0,0)
return ans
Problem D
Split Message Based on Limit
思路
大佬的思路用的暴力,从小到大而枚举分割的数量,注意当数量的位数发生变化时尾部的长度也会发生变化,在代码中使用cap表示当前能最大能存储多少个字符,只有当这个数量大于len(message)时,才找到一个最小长度的划分,代码里的-9、-99、-999时在位数增加时所能存储的有效信息会少一位。最后构造即可
代码
补题代码
class Solution:
def splitMessage(self, message: str, limit: int) -> List[str]:
i,cap = 0,0
n = len(message)
while True:
i+=1
if i <10:
tail = 5
elif i<100:
if i == 10:cap-=9
tail = 7
elif i<1000:
if i == 100:cap-=99
tail = 9
elif i<10000:
if i == 1000:cap-=999
tail = 11
if limit-tail<=0: return []
cap+=limit-tail
if cap < n:continue
ans = []
k = 0
# print(i)
for j in range(1,i+1):
tail = f'<{j}/{i}>'
m = 0
if j<i:
m = limit -len(tail)
ans.append(message[k:k+m]+tail)
else:
ans.append(message[k:]+tail)
k+=m
return ans
总结
出了2题,C题赛后出的,感觉主要问题是B题开始思路想错了,耽误了不少时间,导致C题没调出来,估计要掉分了。
过往不恋 未来不迎 当下不负