记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
- 8/3 1406. 石子游戏 III
- 8/4 3731. 找出缺失的元素
- 8/5 3310. 移除可疑的方法
- 8/6 3345. 最小可整除数位乘积 I
- 8/7 3348. 最小可整除数位乘积 II
- 8/8 3302. 字典序最小的合法序列
- 8/9 1140. 石子游戏 II
8/3 1406. 石子游戏 III
双方每次可从剩余石子堆前端取 1、2 或 3 堆,都采取最优策略。
用 dp[i] 表示从下标 i 开始,当前选手相对对手能多得的最大分数差。
转移为:枚举取 k=1…3 堆,得分为这 k 堆之和减去对方从 i+k 出发的最优差值。
最终看 dp[0]:大于 0 为 Alice,小于 0 为 Bob,等于 0 为 Tie。
defstoneGameIII(stoneValue):""" :type stoneValue: List[int] :rtype: str """n=len(stoneValue)dp0=dp1=dp2=0foriinrange(n-1,-1,-1):best=stoneValue[i]-dp0ifi+1<n:best=max(best,stoneValue[i]+stoneValue[i+1]-dp1)ifi+2<n:best=max(best,stoneValue[i]+stoneValue[i+1]+stoneValue[i+2]-dp2)dp0,dp1,dp2=best,dp0,dp1ifdp0>0:return"Alice"ifdp0<0:return"Bob"return"Tie"8/4 3731. 找出缺失的元素
找到最小值和最大值 便利所有元素 如果不在数组中就加入列表中
deffindMissingElements(nums):""" :type nums: List[int] :rtype: List[int] """minv,maxv=min(nums),max(nums)missing=[]s=set(nums)foriinrange(minv,maxv+1):ifinotins:missing.append(i)returnmissing8/5 3310. 移除可疑的方法
把调用关系建成有向图。从有 bug 的方法 k 出发做 BFS/DFS,标记所有可达方法为可疑。
若存在非可疑方法调用了可疑方法,则整组不能删除,返回全部方法。
否则删除所有可疑方法,返回剩余方法。
defremainingMethods(n,k,invocations):""" :type n: int :type k: int :type invocations: List[List[int]] :rtype: List[int] """fromcollectionsimportdeque g=[[]for_inrange(n)]fora,bininvocations:g[a].append(b)suspicious=[False]*n q=deque([k])suspicious[k]=Truewhileq:u=q.popleft()forving[u]:ifnotsuspicious[v]:suspicious[v]=Trueq.append(v)ans=[]foruinrange(n):ifsuspicious[u]:continueforving[u]:ifsuspicious[v]:returnlist(range(n))ans.append(u)returnans8/6 3345. 最小可整除数位乘积 I
依次增加n 知道找到满足的数
defsmallestNumber(n,t):""" :type n: int :type t: int :rtype: int """defcheck(num):v=1whilenum>0:v*=num%10num//=10returnv%t==0whilenotcheck(n):n+=1returnn8/7 3348. 最小可整除数位乘积 II
答案要求无 0,且数位乘积能被 t 整除,因此 t 的质因子只能是 2、3、5、7,否则无解。
把 t 分解成这些质因子后,用尽量少的数位 2…9 去覆盖(优先拼成 8、9、6、4)。
若最短覆盖长度已超过 num,直接返回该最短数。
否则尽量保持与 num 同长度:从右往左找第一个可增大的位置,增大后用 1 填充多余空位,再接上覆盖剩余质因子的最小后缀。
若同长度无解,则构造长度为 len(num)+1 的数:前面补 1,后面接最短覆盖数位。
defsmallestNumber(num,t):""" :type num: str :type t: int :rtype: str """fromcollectionsimportCounter FACTOR={0:Counter(),1:Counter(),2:Counter([2]),3:Counter([3]),4:Counter([2,2]),5:Counter([5]),6:Counter([2,3]),7:Counter([7]),8:Counter([2,2,2]),9:Counter([3,3]),}defget_prime_count(x):cnt=Counter()forpin(2,3,5,7):whilex%p==0:x//=p cnt[p]+=1returncnt,x==1defget_factor_count(cnt):c8,rem2=divmod(cnt[2],3)c9,c3=divmod(cnt[3],2)c4,c2=divmod(rem2,2)c6=0ifc2==1andc3==1:c2=c3=0c6=1ifc3==1andc4==1:c2,c6,c3,c4=1,1,0,0return{"2":c2,"3":c3,"4":c4,"5":cnt[5],"6":c6,"7":cnt[7],"8":c8,"9":c9,}defbuild(factors):return"".join(d*factors[d]fordin"23456789")need,ok=get_prime_count(t)ifnotok:return"-1"factors=get_factor_count(need)ifsum(factors.values())>len(num):returnbuild(factors)prefix=sum((FACTOR[int(c)]forcinnum),Counter())first_zero=next((ifori,cinenumerate(num)ifc=="0"),len(num))iffirst_zero==len(num)andneed<=prefix:returnnumforiinrange(len(num)-1,-1,-1):d=int(num[i])prefix-=FACTOR[d]space=len(num)-1-iifi>first_zero:continueforbiggerinrange(d+1,10):remain=get_factor_count(need-prefix-FACTOR[bigger])ifsum(remain.values())<=space:ones=space-sum(remain.values())returnnum[:i]+str(bigger)+"1"*ones+build(remain)factors=get_factor_count(need)return"1"*(len(num)+1-sum(factors.values()))+build(factors)8/8 3302. 字典序最小的合法序列
要在 word1 中找一组严格递增下标,使取出的字符与 word2 至多有一处不同,并要求下标序列字典序最小。
先从右往左预处理 last[j]:匹配 word2[j…] 时能取到的最右起点位置。
再从左往右贪心:字符相同则立刻取当前下标;若不同且还没用过那一次修改,并保证后面仍能匹配完(已是最后一位,或当前位置早于 last[j+1]),就在这里使用修改。
若最终匹配完 word2,返回下标序列,否则返回空数组。
defvalidSequence(word1,word2):""" :type word1: str :type word2: str :rtype: List[int] """n,m=len(word1),len(word2)last=[-1]*m i,j=n-1,m-1whilei>=0andj>=0:ifword1[i]==word2[j]:last[j]=i j-=1i-=1ans=[]can_skip=Truej=0fori,cinenumerate(word1):ifj==m:breakifc==word2[j]:ans.append(i)j+=1elifcan_skipand(j==m-1ori<last[j+1]):can_skip=Falseans.append(i)j+=1returnansifj==melse[]8/9 1140. 石子游戏 II
s[i]记录后缀和sum(piles[i:])
如果i+2*m>n 可以把后面的都拿了
遍历所有可能的x 找到后一个步最少的可能性 得到此时最大值
mem记忆(i,m)的结果
defstoneGameII(piles):""" :type piles: List[int] :rtype: int """s=piles[:]n=len(piles)foriinrange(n-2,-1,-1):s[i]+=s[i+1]mem={}defdfs(i,m):if(i,m)inmem:returnmem[(i,m)]ifi+2*m>=n:mem[(i,m)]=s[i]returns[i]ans=s[i]-min(dfs(i+x,max(m,x))forxinrange(1,m*2+1))mem[(i,m)]=ansreturnansreturndfs(0,1)