[LeetCode周赛复盘] 第 336 场周赛20230312
一、本周周赛总结
- 最近真的发现自己笨死。
- T1 枚举。
- T2 贪心。
- T3 前缀异或和+哈希计数。
- T4 贪心/堆。
二、 [Easy] 6315. 统计范围内的元音字符串数
1. 题目描述
2. 思路分析
按题意模拟即可。
3. 代码实现
class Solution:
def vowelStrings(self, words: List[str], left: int, right: int) -> int:
ans = 0
for s in words[left:right+1]:
if s[0] in 'aeiou' and s[-1] in 'aeiou':
ans += 1
return ans
三、[Medium] 6316. 重排数组以得到最大前缀分数
1. 题目描述
2. 思路分析
- 贪心。
- 大的数往前排,前缀和下降越慢。正的前缀和越多。
3. 代码实现
class Solution:
def maxScore(self, nums: List[int]) -> int:
n = len(nums)
nums.sort(reverse=True)
p = list(accumulate(nums))
return sum(x>0 for x in p )
四、[Medium] 6317. 统计美丽子数组数目
链接: 6317. 统计美丽子数组数目
1. 题目描述
2. 思路分析
- 求xxx子数组的数目,一般都是前缀和+哈希。
- 这题拆位分析,发现每次都要减去同位上的两个1才行。
- 那么这个子段里,每位上的1是偶数就可以。
- 对于前缀和的两个边界来说,就是每一位上的1计数后奇偶性相同。
- 我们知道奇偶性相同意味着异或和为0.
- 题目转化为求多少个子段异或和为0。
- 只需要一路求异或和并且用哈希表记录即可。
3. 代码实现
class Solution:
def beautifulSubarrays(self, nums: List[int]) -> int:
n = len(nums)
cnt = Counter([0])
s = 0
ans = 0
for v in nums:
s ^= v
ans += cnt[s]
cnt[s] += 1
return ans
五、[Hard] 6318. 完成所有任务的最少时间
1. 题目描述
2. 思路分析
- 这题不会做,找到原题1e5的代码抄了。
- 赛后学了灵神的n方思路,但nlgn没学会。
- 贪心n方思路。
- 开一个work = [False] * 2001记录每个时间点是否工作。
- 把每个任务按结束时间排序,那么每个新任务和前边的交集,只能是前边那个任务的后缀。
- 贪心的让每个任务执行时间排在后缀上,则更有可能覆盖后边的任务。
- 每次新任务检查区间内已经工作的时间减去,如果还剩余时间,则从后往前枚举时间点减去即可。
- 最后sum(work)。
3. 代码实现
class Solution:
def findMinimumTime(self, tasks: List[List[int]]) -> int:
tasks.sort(key=lambda x:x[1])
work = [0] * 2001
for s,e,d in tasks:
d -= sum(work[s:e+1])
if d > 0:
for i in range(e,s-1,-1):
if not work[i]:
work[i] = 1
d -= 1
if not d:
break
return sum(work)
class Solution:
def findMinimumTime(self, tasks: List[List[int]]) -> int:
# n = len(tasks)
# task.sort()
tasks.append([10**9+1, 10**9+1, 1]) #加个哨兵
res, q = 0, []
for [s, e, p] in sorted(tasks, key=lambda x:x[0]) :
while q and q[0][0]+res < s :
if q[0][0]+res >= q[0][1]: heapq.heappop(q) #任务早已完成,移除
else : res += min(q[0][1], s) - (q[0][0]+res)
heapq.heappush(q, [e-p+1-res, e+1])
return res