Leetcode周赛_203学习笔记

学习来源:

leetcode官方题解&评论区大佬的题解

1560 圆形赛道上经过次数最多的扇区

算法分析:题目只要求取被访问次数最多的扇区,因此可以只看开始位置与结束位置。中间必定是所有的扇区都访问了0,1,2,…遍。对最后的判定无影响。

res = []
start = rounds[0]
end = rounds[-1]
length = end - start
if length < 0:
    length += n
while length > -1:
    if start+length>n:
        res.append((start+length)%n)
    else:
        res.append(start+length)
    length -= 1
res.sort()
return res
1561 可以获得的最大硬币数目

算法分析:先将数组排序,尾指针每次前移两个元素,头指针每次后移一个元素。

piles.sort()
res = 0
l = 0
# len(piles)-1表示最大的硬币堆,依题意会被Alice拿走,因此选择len(piles)-2开始拿取
r = len(piles)-2
while l<r:
    res += piles[r]
    l += 1
    r -= 2
return res
1562 查找大小为M的最新分组

算法分析:设定border[i]表示以i为边界的连续的1的长度,num[i]表示长度为i的连续1的个数。若当前操作位置为pos,则该位置左边连续1的长度为border[pos-1]右边的连续1的长度为border[pos+1],更新后num[border[pos-1]]num[border[pos+1]]减少1num[border[pos - 1] + 1 + border[pos + 1]]1。每次更新后判断num[m]是否大于0,即是否存在长度为m的连续1

lens = len(arr)
# border[i]表示以i为边界的连续的1的长度
border = [0 for _ in range(lens+2)]pos
# num[i]表示长度为i的连续1的个数
num = [0 for _ in range(lens+1)]
res = -1

for count, pos in enumerate(arr):
    left = border[pos - 1]
    right = border[pos + 1]
    new_length = right + left + 1
    border[pos - left] = border[pos + right] = new_length
    num[new_length] += 1
    num[left] -= 1
    num[right] -= 1
    # 若num[m]>0说明此时存在长度为m的连续1,更新结果
    if num[m] > 0:
        res = count+1

return res
1563 石子游戏

题意理解:将给定数组划分为非空的两段,舍弃元素总和更大的子段,得分累加另一子段的元素和。重复进行此操作,直至只剩下一个元素,求解最大的得分。
示例stoneValue = [1,2,2],第一次划分为:L=[1]R=[2,2],则sum(L)=1sum(R)=4,即舍去右边,得分累加左边sum(L)。此时只剩下一个元素,结束操作,最终得分为1。若第一次划分为:L=[1,2]R=[2],则sum(L)=3sum(R)=2,即舍去左边,得分累加右边sum(R)。此时只剩下一个元素,结束操作,最终得分为2。最终答案为2
算法分析:区间动态规划,dp[i][j]表示左右边界为ij时的最优解。

lens =len(stoneValue)
# sum[i][j]表示stoneValue中i到j的元素和
sum_num = [[0 for _ in range(lens)] for _ in range(lens)]
for i in range(lens):
    sum_num[i][i] = stoneValue[i]
    for j in range(i+1,lens):
        sum_num[i][j] = sum_num[i][j-1]+stoneValue[j]
# dp[i][j]表示左边界为i,右边界为j的stoneValue的最优解
dp = [[0 for _ in range(lens)] for _ in range(lens)]

def maxres(start,end,sum_num):
	# 只剩下一个石头,返回0
    if start == end:
        dp[start][end] = 0
        return dp[start][end]
    # 避免重复计算
    if not dp[start][end]:
    	# 遍历start到end中所有可能的划分位置
        for i in range(start,end):
            left = sum_num[start][i]
            right = sum_num[i+1][end]
            # 左边小于右边,右边被舍弃
            if left < right:
                dp[start][end] = max(dp[start][end],left + maxres(start,i,sum_num))
            # 右边小于左边,左边被舍弃
            elif left > right:
                dp[start][end] = max(dp[start][end],right + maxres(i+1,end,sum_num))
            # 两边相等,dp寻找两边的最优解
            else:
                dp[start][end] = max(dp[start][end],left + maxres(start,i,sum_num),right + maxres(i+1,end,sum_num))
    return dp[start][end]

maxres(0,lens-1,sum_num)
return dp[0][lens-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值