本文已参与「新人创作礼」活动,一起开启掘金创作之路。
2022-01-30 每日打卡:Leetcode第278场周赛
写在前面
“这些事儿在熟练之后,也许就像喝口水一样平淡,但却能给初学者带来巨大的快乐,我一直觉得,能否始终保持如初学者般的热情、专注,决定了在做某件事时能走多远,能做多好。” 该系列文章由python编写,所刷题目共三个来源:之前没做出来的 ;Leetcode中等,困难难度题目; 周赛题目;某个专题的经典题目,所有代码已AC。每日1-3道,随缘剖析,希望风雨无阻,作为勉励自己坚持刷题的记录。
T1~T2
- T1:思路定了以后对于循环的退出位置其实细想一下就好,不要懒的直接去试,这次一次过了,但比较慢,下次争取控制在1min内。
- T2:计算【不确定的最值对应的列表】也可以通过一遍遍历,无须借助字典完成,以最大值为例,如果大于的时候一定是第一次出现,此时新建列表,如果等于最大值,此时列表一定存在。
- T2:【10^5次方】不要尝试遍历了,使用前缀和或者滑动窗口差不多。
5994. 查找给定哈希值的子串(T3)
-
指数运算非常非常慢,尤其是
**和pow()的时间复杂度为 O ( l o g n ) O(logn) O(logn)。所以尽量把指数运算的部分作为常量,或者使用累乘的方法,比如题目中需要计算这个公式: h a s h ( s , p , m ) = ( v a l ( s [ 0 ] ) ∗ p 0 + v a l ( s [ 1 ] ) ∗ p 1 + . . . + v a l ( s [ k − 1 ] ) ∗ p k − 1 ) m o d m hash(s, p, m) = (val(s[0]) * p0 + val(s[1]) * p1 + ... + val(s[k-1]) * pk-1) mod m hash(s,p,m)=(val(s[0])∗p0+val(s[1])∗p1+...+val(s[k−1])∗pk−1)modm- 使用while循环中一个变量单独表示exp,每次循环
exp *= p也远远快于pow(p, _)。 - 使用等比数列计算公式,但是注意大数取余问题!取余公式。顺便复习了一下两种常用的指数取余方法(T14),循环取余和快速幂。
- 使用while循环中一个变量单独表示exp,每次循环
-
很有趣的一点是我发现前面的几位都是使用的都是【倒序计算】,从最后一位开始计算最后一个窗口的。明白过来是因为这个题中虽然滑动窗口【一定能整除】,但是涉及大数问题的除法时,往往会有这么一个报错
OverflowError: integer division result too large for a float。- python中整数没有位数限制,但浮点数有,这也是为什么inf写在了float中,所以【一定能整除的可以直接使用
//而不是/】 - 更严谨的做法就是反向推导,从前往后需要除,那从后往前就好了,把除法变成乘法
- python中整数没有位数限制,但浮点数有,这也是为什么inf写在了float中,所以【一定能整除的可以直接使用
5995. 字符串分组(T4)
思路比较简单,就是并查集+二进制状态压缩。不过相对于可能面临的 1 0 4 10^4 104 数据,两两检查是否match显然是不科学的,所以采用对于每一个未检查的结点,【枚举+哈希表查找】其可能衍生的词是否在words中,因为衍生的可能性是常数级别:
class Solution:
def groupStrings(self, words: List[str]) -> List[int]:
# 使用哈希映射统计每一个二进制表示出现的次数
wordmasks = Counter()
for word in words:
mask = 0
for ch in word:
mask |= (1 << (ord(ch) - ord("a")))
wordmasks[mask] += 1
# 辅助函数,用来得到 mask 的所有可能的相邻节点
def get_adjacent(mask: int) -> List[int]:
adj = list()
# 将一个 0 变成 1,或将一个 1 变成 0
for i in range(26):
adj.append(mask ^ (1 << i))
# 将一个 0 变成 1,且将一个 1 变成 0
for i in range(26):
if mask & (1 << i):
for j in range(26):
if not (mask & (1 << j)):
adj.append(mask ^ (1 << i) ^ (1 << j))
return adj
used = set()
best = cnt = 0
for mask, occ in wordmasks.items():
if mask in used:
continue
# 从一个未搜索过的节点开始进行广度优先搜索,并求出对应连通分量的大小
q = deque([mask])
used.add(mask)
# total 记录联通分量的大小
total = occ
while q:
u = q.popleft()
for v in get_adjacent(u):
if v in wordmasks and v not in used:
q.append(v)
used.add(v)
total += wordmasks[v]
best = max(best, total)
cnt += 1
return [cnt, best]
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/groups-of-strings/solution/zi-fu-chuan-fen-zu-by-leetcode-solution-a8dr/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。