[LeetCode周赛复盘] 第 327 场周赛20230108
- 一、本周周赛总结
- 二、 [Easy] 6283. 正整数和负整数的最大计数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 三、[Medium] 6285. 执行 K 次操作后的最大分数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 四、[Medium] 6284. 使字符串总不同字符的数目相等
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 五、[Hard] 6306. 过桥的时间
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 六、参考链接
一、本周周赛总结
- 这场阳了没敢打,也忘了,半小时后开机,大概12:18做完。T4堆模拟,大概还是能上分。
- T1 模拟或二分。
- T2 堆模拟
- T3 集合模拟。
- T4 四个堆模板。
二、 [Easy] 6283. 正整数和负整数的最大计数
链接: 6283. 正整数和负整数的最大计数
1. 题目描述
2. 思路分析
按题意模拟即可。
- 由于题目是有序的,二分也可以。
3. 代码实现
class Solution:
def maximumCount(self, nums: List[int]) -> int:
c = Counter()
for x in nums:
if x :
c[x//abs(x)] += 1
return max(c[-1],c[1])
三、[Medium] 6285. 执行 K 次操作后的最大分数
链接: 6285. 执行 K 次操作后的最大分数
1. 题目描述
2. 思路分析
- 题意很明显的指向堆。
3. 代码实现
class Solution:
def maxKelements(self, nums: List[int], k: int) -> int:
h = []
for x in nums:
heappush(h,-x)
ans = 0
for _ in range(k):
a = -heappop(h)
ans += a
a = (a+3-1)//3
heappush(h,-a)
return ans
四、[Medium] 6284. 使字符串总不同字符的数目相等
链接: 6284. 使字符串总不同字符的数目相等
1. 题目描述
2. 思路分析
- 虽然两个单词长度很大,但是其实只有小写字母,因此去重后就是26.可以暴力枚举。
- 用w1 w2承载原单词的集合。
- 然后分别计数。
- 从计数中枚举要交换的字母,如果计数大于1则集合不变,==1则去掉这个字符。
- 然后判断两边是否一样长即可。
3. 代码实现
class Solution:
def isItPossible(self, word1: str, word2: str) -> bool:
w1 = set(word1)
w2 = set(word2)
c1 = Counter(word1)
c2 = Counter(word2)
for a,b in c1.items():
l = w1 if b>1 else w1-{a} # 左集合去掉a
for c,d in c2.items():
r = w2 if d >1 else w2 - {c} # 右集合去掉c
if len(l|{c}) == len(r|{a}): # 左集合+c,右集合+a
return True
return False
五、[Hard] 6306. 过桥的时间
链接: 6306. 过桥的时间
1. 题目描述
2. 思路分析
- 四个堆的含义分别是:
- l:左边等上桥的人,大顶堆储存优先级,决定让谁上
- r: 右边等上桥的人,大顶堆
- t1: 左边正在搬东西的人,小顶堆,储存它搬完东西准备上桥的时间。
- t2: 右边正在搬东西的人,同上。
- 其中t1里的人将向l走,t2里的人将向r走。
- 显然时间的卡点在桥每次只能有一个人走,所有人都在等桥空,因此我们用ans代表桥空下来的时间。
- 活没干完时,即桥右侧有人没回来或者n>0,进行计算,我这里直接while True了。
- 显然先把t1t2队伍里<=ans的人都追加到各自队伍里。
- 如果这时还没人等桥,但活又没干完,那就加速(not r and (not l or not n)),即必须找人等桥,ans追到第一个等桥的那一刻。
- 否则找一个人过桥。这个规则就是题面里,先从r里选,否则从l里选(同时n>0)。
- r里的人过桥:从r中pop一个老哥,ans更新为它的过桥时间,给t1追加一个这老哥卸完货开始等桥的时间。
- l里的人过桥:从l中pop一个老哥,ans更新为它的过桥时间,给t2追加一个这老哥上完或开始等桥的时间。
3. 代码实现
class Solution:
def findCrossingTime(self, n: int, k: int, time: List[List[int]]) -> int:
l, r, t1, t2 = [], [], [], [] # 左边等上桥的人大顶堆、右边等上桥的人大顶堆、左边正在搬的人小顶堆、右边正在搬的人小顶堆
for i, (lr, po, rl, pn) in enumerate(time):
heappush(l, (-lr - rl, -i))
ans = 0 # 桥空下来的时间
while n or r or t2:
while t1 and t1[0][0] <= ans: # 当前时间桥左侧都有谁等待
_, i = heappop(t1)
heappush(l, (-time[i][0] - time[i][2], -i)) # 只存优先级和人
while t2 and t2[0][0] <= ans: # 当前时间桥右侧都有谁等待
_, i = heappop(t2)
heappush(r, (-time[i][0] - time[i][2], -i))
if not r and (not l or not n): # 如果右侧没人等了,且左侧没人等且还得搬(即活没结束,但没有等桥的),让时间前进,找一个最早需要上桥的人
ans = 1e9
if t1:
ans = t1[0][0]
if t2:
ans = min(ans, t2[0][0])
continue
if r: # 当前时间如果桥右侧有人等,就让他走
_, i = heappop(r)
i = -i
ans = ans + time[i][2]
heappush(t1, (ans + time[i][3], i)) # 这个人加入左侧等待队伍,保存什么时候开始等桥
elif n: # 右侧没人等待,还有箱子,左侧才上桥
_, i = heappop(l)
i = -i
ans = ans + time[i][0]
heappush(t2, (ans + time[i][1], i))
n -= 1
# if not n and not r and not t2: # 如果箱子没了,且右侧没人等了
# break
return ans