T1
https://leetcode-cn.com/problems/most-visited-sector-in-a-circular-track/
虽然直接模拟是一个办法,但是实际上兜了N圈之后最后多出来的部分就是所求
即:1→3→2→4 等效于 1→4
class Solution:
def mostVisited(self, n: int, rounds: List[int]) -> List[int]:
s, e = rounds[0], rounds[-1]
if s <= e:
# [起点, 终点]
return list(range(s, e + 1))
else:
# [1, 终点]+[起点, n]
return list(range(1, e + 1)) + list(range(s, n + 1))
T2
https://leetcode-cn.com/problems/maximum-number-of-coins-you-can-get/
贪心,排序后令A拿最多的一堆,自己拿第二多的,B拿最少的。
所以做法就是排序
class Solution:
def maxCoins(self, piles: List[int]) -> int:
piles.sort()
res=0
while piles:
piles.pop()
res+=piles.pop()
piles.pop(0)
'''
这里应该用其他方法降低pop(0),比如计数器,但是比赛的时候还是写的快不就完事了(
'''
return res
T3
https://leetcode-cn.com/problems/find-latest-group-of-size-m/
这题一开始想的是二分查找,但是会遇到(没有m个)(有m个)(没有m个)的情形,所以不行
所以做法是维护区间左右端点。
class Solution:
def findLatestStep(self, arr: List[int], m: int) -> int:
LR = {}
cnt = collections.defaultdict(int)
latest = -1
for i,c in enumerate(arr):
L = c if c not in LR else LR[c]
'''
找左端点
'''
R = c+1 if c+1 not in LR else LR[c+1]
'''
找右端点
'''
cnt[R-L]+=1
cnt[R-c-1]-=1
cnt[c-L]-=1
LR[L]=R
LR[R]=L
if cnt[m]>0:
latest = i+1
return latest
T4
https://leetcode-cn.com/problems/stone-game-v/
区间DP,状态转移方程为:
dp(i,j) 表示左右端点为i,j时,能获得的最大得分
=(i,k)区间和较小时:dp(i,k)+sum(i,k)【sum(i,k)表示i到k的区间和】
=(k,j)区间和较小时:dp(k,j)+sum(k,j)
=和相等时:max(dp(i,k),dp(k,j))+sum(k,j)
上述三者最大值,k取值为[i+1,j-1]
基本情况为:
dp(i,i+1)=dp(i,i)=0
所以很容易写出超时代码:
利用前缀和数组以后很容易AC:
class Solution:
def stoneGameV(self, stoneValue: List[int]) -> int:
sums=[0]
for ni in stoneValue:
sums.append(ni+sums[-1])
@lru_cache(None)
def helper(left,right):
if right-1==left or left==right:
return 0
res=0
l,r=sums[left],sums[right]
for k in range(left+1,right):
ks=sums[k]
if ks-l<r-ks:
res=max(res,ks-l+helper(left,k))
elif ks-l>r-ks:
res=max(res,r-ks+helper(k,right))
else:
res=max(res,ks-l + max(helper(left,k),helper(k,right)))
return res
return helper(0,len(stoneValue))