年初三的比赛,本来其实不太想打的,最近因为一些原因状态上感觉是那种比较低落的状态,打比赛估计不会获得什么好名次,但是挺怕一次放过了我自己之后后面就会把这种放弃当成是常态了,因此最后还是咬着牙打了比赛。所幸运气还算好,最终还是4题都做出来了,虽然最后一题很蠢的画蛇添足导致不断地超时影响了最后的排名,但是终究4题都做出来的成绩差也差不到哪里去,反正就我个人而言还算是一个聊以慰藉的名次吧……
又及,拖到现在才发绝不是因为过年玩high了忘了这茬事了哈……
给出题目一的试题链接如下:
这一题的思路挺直接的,因为最终的结果要么就是0101
的重复字符串,要么就是1010
的重复字符串。
因此,我们只需要考察以下这两种情况下所需要经历的操作次数然后取其中较小的数即可得到最终的结果。
给出python代码实现如下:
class Solution:
def minOperations(self, s: str) -> int:
odd = 0
even = 0
for i, c in enumerate(s):
if i % 2 == 0:
if c == "0":
even += 1
else:
odd += 1
else:
if c == "1":
even += 1
else:
odd += 1
return min(odd, even)
提交代码评测得到:耗时48ms,占用内存14.4MB。
给出题目二的试题链接如下:
这一题一开始绕了点弯子,但是后面想想其实也蛮直接的,就是首先统计同一字符连续出现的次数,然后分别计算其重复次数即可。
显然,对于某一个重复次数为n,长度为l的连续子串,其内部包含的同构字符串个数为 n ⋅ k ⋅ ( k + 1 ) 2 n\cdot \frac{k\cdot(k+1)}{2} n⋅2k⋅(k+1)。
因此,我们可以快速地给出我们最终的代码实现如下。
给出python代码实现如下:
class Solution:
def countHomogenous(self, s: str) -> int:
MOD = 10**9+7
cache = {
}
cnt = 0
for idx, c in enumerate(s):
if idx == 0:
cnt += 1
else:
last = s[idx-1]
if c == last:
cnt += 1
else:
if last not in cache:
cache[last] = {
}
if cnt not in cache[last]:
cache[last][cnt] = 0
cache[last][cnt] += 1
cnt = 1
last = s[-1]
if last not in cache:
cache[last] = {
}
if cnt not in cache[last]:
cache[last][cnt] = 0
cache[last][cnt] += 1
# print(cache)
res = 0
for item in cache.values():
for cnt, repeat in item.items():
res = (res + repeat * cnt * (cnt+1) // 2) % MOD
return res
提交代码评测得到:耗时212ms,占用内存15.1MB。
给出题目三的试题链接如下:
这一题拿到手之后最开始的思路是尝试使用greedy的方式考察怎么对袋子内的球进行分割,尝试直接在优先操作次数内获得最大的球数。
但是,后来发现greedy的思路似乎不可行,因为每个袋子内的球应该怎么进行分割受到其他袋子内的球的数目以及允许的最大操作次数有关。
因此,我们只能转换思路,使用二分法直接对答案进行搜索,此时可以通过测试。
给出python代码实现如下:
class Solution:
def minimumSize(self, nums: List[int], maxOperations: int) -> int:
_min = 1
_max = max(nums)
nums = Counter(nums)
def count_op(nums, tgt):
res = 0
for n, t in nums.items():
res += t * ((n-1) // tgt)
return res
if count_op(nums, _min) <= maxOperations:
return _min
while _min < _max-1:
m = (_min + _max) // 2
if count_op(nums, m) <= maxOperations:
_max = m
else:
_min = m
return _max
提交代码评测得到:耗时1448ms,占用内存29.8MB。
给出题目四的试题链接如下:
这一题的思路倒是一开始就想对了,但是实现细节上没想得很明白,导致一开始超时了n次,最后勉勉强强过了之后,运行效率上也惨不忍睹。
最坑的是,最后发现,我的解法与当前的最优算法实现之间只相差了一个排序,真的是瞬间崩溃了……
话不多说,直接说解法吧,其实挺简单的,就是统计所有可以组成连通三元组的元素,然后计算其度数之后找到其中最小的值。
因此,我们只需要首先记录下所有节点的连接节点,然后对每一条边的两个节点找到与两个节点均相连的节点进行统计,然后计算度数即可。
只是,如果遍历全部的边,也可以通过,但是效率过低,但是如果先按照每一个节点的连接度数进行排序,就可以优化程序的执行效率,将整体的执行效率提升一个量级以上。
这里,我们就不给我们的代码了,直接给出官网中最优的代码实现如下。
class Solution:
def minTrioDegree(self, n: int, edges: List[List[int]]) -> int:
graph=collections.defaultdict(set)
for x,y in edges:
graph[x].add(y)
graph[y].add(x)
nds=sorted([[len(graph[x]),x] for x in graph])
nnds=sorted([[len(graph[x])+len(graph[y]),x,y] for x,y in edges])
ans=3*n*(n-1)
for w0,x,y in nnds:
if w0>=ans:
break
for w1,z in nds:
if w0+w1>=ans:
break
if z in graph[x] and z in graph[y]:
ans=min(ans,w0+w1)
break
return ans-6 if ans<3*n*(n-1) else -1
如前所述,上述代码较之我们的实现就多了两个排序,然后执行效率提升了1个量级以上。
最终,提交代码评测得到:耗时648ms,占用内存51MB。