记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
可以将25ml看作1份 四种情况分别为
A 4 B 0
A 3 B 1
A 2 B 2
A 1 B 3
开始时 A,B拥有的份数一样
当n过大时 A被取完的概率接近于1 误差小于10^-5
假设dp[i][j] 为A剩余i份 B剩余j份时 需要求的概率
dp[i][j] = (dp[i-4][j]+dp[i-3][j-1]+dp[i-2][j-2]+dp[i-1][j-3])/4
当j=0,i>0时 dp[i][j] = 0
当i=0,j>0时 dp[i][j] = 1
当i=0,j=0时 dp[i][j] = 0.5
def soupServings(n):
"""
:type n: int
:rtype: float
"""
n = (n+24)//25
if n>=179:
return 1
dp = [[0]*(n+1) for _ in range(n+1)]
dp[0] = [0.5]+[1.0]*n
for i in range(1,n+1):
for j in range(1,n+1):
dp[i][j] = (dp[max(0, i - 4)][j] +
dp[max(0, i - 3)][max(0, j - 1)] +
dp[max(0, i - 2)][max(0, j - 2)] +
dp[max(0, i - 1)][max(0, j - 3)])/4
return dp[n][n]
f(x)表示小于等于x内的神奇数字数目 c为a,b最小公倍数lcm
f(x)=x//a+x//b-x//c
f(x)随x增加单调不减 所以可以二分查找第n个神奇数字
def nthMagicalNumber(n, a, b):
"""
:type n: int
:type a: int
:type b: int
:rtype: int
"""
def lcm(a,b):
x,y = a,b
if a<b:
x,y = b,a
while y>0:
x,y = y,x%y
return a*b/x
MOD = 10**9+7
l,r = min(a,b),min(a,b)*n
c = lcm(a,b)
while l<=r:
mid = (l+r)>>1
s = mid//a+mid//b-mid//c
if s>=n:
r = mid-1
else:
l = mid+1
return (r+1)%MOD
用map存储每个盒子内的小球数
def countBalls(lowLimit, highLimit):
"""
:type lowLimit: int
:type highLimit: int
:rtype: int
"""
def func(x):
tag = 0
while x>0:
tag += x%10
x = x//10
return tag
dic = {}
ans = 0
for i in range(lowLimit,highLimit+1):
tag = func(i)
dic[tag] = dic.get(tag,0)+1
if dic[tag]>ans:
ans = dic[tag]
return ans
子数组最大值不能大于right 且范围内至少有一个处于[left,right]间
l表示上次出现大于right的位置
r表示上次出现left,right之间的位置
对于当前位置i 可以有r-l个选择
遍历每一个位置可以得到答案
def numSubarrayBoundedMax(nums, left, right):
"""
:type nums: List[int]
:type left: int
:type right: int
:rtype: int
"""
ans = 0
l,r = -1,-1
for i,num in enumerate(nums):
if left<=num<=right:
r = i
elif num>right:
l = i
r = -1
if r!=-1:
ans += r-l
return ans
func 将字符串中连续相同的字母压缩成一个字母+出现的次数
比较原始s和需要比较的字符串w 压缩后的状态
需要满足 长度相等 每个位置上的字母需要一样
出现的次数 s和w相同 或者s>w 并且s的次数大于等于3
def expressiveWords(s, words):
"""
:type s: str
:type words: List[str]
:rtype: int
"""
def func(s):
l = []
cur = ""
num = 0
for c in s:
if cur=="":
cur = c
num=1
elif cur==c:
num+=1
else:
l.append((cur,num))
cur = c
num = 1
l.append((cur,num))
return l
sl = func(s)
ans = 0
for w in words:
wl = func(w)
if len(wl)!=len(sl):
continue
tag = True
for i in range(len(sl)):
if sl[i][0]!=wl[i][0]:
tag = False
break
if wl[i][1]==sl[i][1] or (sl[i][1]>wl[i][1] and sl[i][1]>=3):
continue
else:
tag = False
break
if tag:
ans+=1
return ans
原始节点间的细分节点数可看做节点间的距离
使用dijkstra 可以算出起点到个点的最短路径 记录可达的原始节点数
哈希表used[(u,v)]记录节点u到v可达的细分节点 (v,u)记录v到u可达的细分节点
最后统计时相加 并不大于u,v间的细分节点总数
def reachableNodes(edges, maxMoves, n):
"""
:type edges: List[List[int]]
:type maxMoves: int
:type n: int
:rtype: int
"""
import heapq
from collections import defaultdict
l = defaultdict(list)
for u,v,n in edges:
l[u].append([v,n])
l[v].append([u,n])
used = {}
visited = set()
ans = 0
pq = [(0,0)]
heapq.heapify(pq)
while pq and pq[0][0]<=maxMoves:
step,u = heapq.heappop(pq)
if u in visited:
continue
visited.add(u)
ans +=1
for v,nodes in l[u]:
if nodes+step+1<=maxMoves and v not in visited:
heapq.heappush(pq,[nodes+step+1,v])
used[(u,v)] = min(nodes,maxMoves-step)
for u,v,n in edges:
ans += min(n,used.get((u,v),0)+used.get((v,u),0))
return ans