这次的比赛和昨晚也差不多,不过第三题傻逼了,一个低级错误导致连错了4次,然后就啥都就不回来了,看了一下国内排名大约被拉了100名吧,唉,要不肯定能进前5%的……
给出题目一的试题链接如下:
这次的第一题实在是不想多说什么,难点完全在于理解题意,说白了就是所有的1事实上都要连在一起,然后只要有1个就算连续……
所以代码其实就很好写,问题就是你题目是否能一次性理解了……
给出python代码实现如下:
class Solution:
def checkOnesSegment(self, s: str) -> bool:
res = 0
n = len(s)
cnt = 0
for c in s:
if c == '0':
if cnt > 0:
res += 1
cnt = 0
else:
cnt += 1
if cnt > 0:
res += 1
return res <= 1
提交代码评测得到:耗时28ms,占用内存14MB。
给出题目二的试题链接如下:
这一题其实是我感觉的这次比赛当中最为简单的一道题,只要先算出与目标的差值,然后尽可能快速地填充就行了。
由于能够用于填充的数的绝对值有上限,因此事实上就是不断地用最大值进行填充直至可以覆盖就行了。
给出python代码实现如下:
class Solution:
def minElements(self, nums: List[int], limit: int, goal: int) -> int:
delta = abs(sum(nums) - goal)
return (delta-1) // limit + 1
提交代码评测得到:耗时724ms,占用内存26.9MB。
给出题目三的试题链接如下:
这一题坦率地说思路上虽然感觉有点复杂,但是挺顺利成章的,只可惜比赛的时候我犯了一个傻逼错误,然后就导致连错了4次,真的是累感不爱,但是有一说一,确实还是挺直接的。
思路上而言,感觉就是:
其中,对于第一步,我们可以采用逐步遍历的方式进行搜索,而对于第二步,就是一个动态规划的问题……
我们给出python代码实现如下:
class Solution:
def countRestrictedPaths(self, n: int, edges: List[List[int]]) -> int:
MOD = 10**9 + 7
edgelist = {
}
graph = defaultdict(set)
for u, v, d in edges:
graph[u].add(v)
graph[v].add(u)
u, v = (u, v) if u < v else (v, u)
if (u, v) not in edgelist:
edgelist[(u, v)] = d
else:
edgelist[(u, v)] = min(d, edgelist[(u, v)])
distance = [-1 for _ in range(n+1)]
q = [(0, n)]
while q:
dis, u = heapq.heappop(q)
if distance[u] != -1:
continue
distance[u] = dis
for v in graph[u]:
if distance[v] == -1:
uu, vv = (u, v) if u < v else (v, u)
heapq.heappush(q, (dis + edgelist[(uu, vv)], v))
@lru_cache(None)
def dp(u):
if u == n:
return 1
res = 0
for v in graph[u]:
if distance[v] < distance[u]:
res += dp(v) % MOD
return res % MOD
return dp(1)
提交代码评测得到:耗时1744ms,占用内存63MB。
给出题目四的试题链接如下:
这一题现在想来其实感觉挺坑的,比赛的时候没能做出来,然后赛后看了一下答案之后发现还是一样的思路,然后重写了一下之后这次就过了……
果然是比赛的时候脑子太乱了的关系吧,或许,大概……
话不多说,这道题核心就是在于想明白最终的答案一定满足条件:
因此,事实上我们就是先将所有对k余数相同的的数组成一个集合进行考察,统计其中数据的分布。
对于最终的答案,可以想见的是,他一定满足:
因此,我们只要分别考察每一个余数下的堆作为补充值的情况就可以了。
不过需要注意的是,由于对于某一个确定的余数位置,它的可用候选值可能有多个(比如1和2的频数均为3,那么这个位置下的数即可以选1也可以选2),因此,我们可以使用一个迭代算法来处理这个问题。
借用缓存机制,这就可以转换为一个动态规划的算法。
不过,即便如此,该算法还是会出现超时问题,因此,我们还需要对其来做一下剪枝。
给出最终的算法实现如下:
class Solution:
def minChanges(self, nums: List[int], k: int) -> int:
cnt = [defaultdict(int) for _ in range(k)]
for i, x in enumerate(nums):
cnt[i % k][x] += 1
def get_max(counter):
_max = max(counter.values())
return [x for x in counter if counter[x] == _max]
cand = [get_max(c) for c in cnt]
tot = sum([c[x[0]] for c, x in zip(cnt, cand)])
n = len(nums)
res = n-k+1
@lru_cache(None)
def dp(i, idx, s):
nonlocal res
if i == k:
if idx != -1:
res = min(res, n - (tot - cnt[idx][cand[idx][0]] + cnt[idx][s]))
# print(f"update res to {res}")
return
if idx == -1:
dp(i+1, i, s)
else:
if n - (tot - cnt[idx][cand[idx][0]]) >= res:
return
for c in cand[i]:
dp(i+1, idx, s^c)
return
dp(0, -1, 0)
return res
提交代码评测得到:耗时5792ms,占用内存343.1MB。