不知道是不是错觉,双周赛感觉是要比周赛多少简单一点,这一次的题目又是全部搞定了,总共耗时52分钟,不过错了两次,因此最终的成绩在1h,很可惜的刚好跑出了全国前100(102名),全球的成绩则为268名,除了上上周那次前两百的成绩,这次算是最好的一次战绩了。
加油,再接再厉,再接再厉,争取有一天可以把成绩稳定到这个水平!
给出题目一的试题链接如下:
这一题的思路没啥好多说的,就是暴力的遍历一下两条对角线然后求一下和就行了,对于 N × N N \times N N×N的矩阵,时间复杂度就是 O ( N ) O(N) O(N),唯一需要注意一下的就是当N为奇数时,两条对角线都会经过中点,需要去一下重。
给出python代码实现如下:
class Solution:
def diagonalSum(self, mat: List[List[int]]) -> int:
n = len(mat)
ans = 0
for i in range(n):
ans += mat[i][i] + mat[i][n-1-i]
if i == n-1-i:
ans -= mat[i][i]
return ans
提交代码后评测得到:耗时116ms,占用内存13.8MB。虽然不是当前的最优解,但是完全是实现细节上有所差别,这里就不再赘述了。
给出题目二的试题链接如下:
这一题事实上也还好,就是统计有多少个1:
我们将上述代码思路转换为python代码即有:
class Solution:
def numWays(self, s: str) -> int:
MOD = 1000000007
one_count = 0
zero_count = 0
cache = {
}
for c in s:
if c == '0':
zero_count += 1
else:
one_count += 1
cache[one_count] = zero_count
zero_count = 0
if one_count not in cache.keys():
cache[one_count] = zero_count
if one_count % 3 != 0:
return 0
elif one_count == 0:
return (zero_count-2) * (zero_count-1) // 2 % MOD
else:
return (cache[one_count // 3 +1] + 1) * (cache[one_count // 3 * 2 +1] + 1) % MOD
提交代码评测得到:耗时112ms,占用内存14.7MB。
emmmm,不用吐槽这里的变量命名,我懂得,但是实在没想到什么好的命名方法,然后比赛的时候又赶时间,然后就变成这副德行了。。。(。>︿<)_θ
另外当前的最优解耗时88ms,但是看了一下,思路是完全相同的,所以这里也就不再多做赘述了。
给出题目三的试题链接如下:
这一题算是我这次比赛里面做的最失败的一题了,先是题目理解错误,再是又出现了一次边界条件没想清楚,结果就呵呵了。
这题最需要注意的是,他这里的删除的子串是一段连续的子串,而不是可以任意选择每个元素是否进行删除,如果是后者的话就要用迭代的方式进行考察了,但是这里既然要求只能删除连续的一串子串,那么事实上题目就被大大简化了。
在只能删除一串子串的情况下,保留下来的子序列就一定是一段头部的序列加上一段尾部的序列(两者可以为空),因此,我们只要找到头部的最长连续非减子串以及尾部的最长连续非减子串,然后将两者进行合并即可。
我们可以将上述思路进一步细化到下述解题步骤:
此时,总长度减去保留下来的子串的长度就是我们最少需要删除的序列长度了。
给出上述思路下的代码实现如下:
class Solution:
def findLengthOfShortestSubarray(self, arr: List[int]) -> int:
n = len(arr)
if n == 1:
return 0
st_last = n-1
for i in range(n-1):
if arr[i+1] < arr[i]:
st_last = i
break
if st_last == n-1:
return 0
ed_first = 0
for i in range(n-1, 0, -1):
if arr[i-1] > arr[i]:
ed_first = i
break
@lru_cache(None)
def merge(st_last, ed_first):
if st_last == -1 or ed_first == n or arr[st_last] <= arr[ed_first]:
return st_last + 1 + n - ed_first
else:
return max(merge(st_last-1, ed_first), merge(st_last, ed_first+1))
left_len = merge(st_last, ed_first)
return n - left_len
提交代码之后评测得到:耗时640ms,占用内存42.6MB。为当前的最优解法。
给出题目四的试题链接如下:
虽然这一题的难度划分是hard,但是较之上一题,这一题的解题思路事实上会更加清晰一些。
我们只需要一直走,直到走到没油为止即可。
可以同一个递归的思路来解这道题:
需要注意的是,直接这么迭代一定会出现超时的问题,需要使用动态规划的方式用空间换取时间。
不过,这里,我们就采用python的缓存机制来直接暴力求解了。
给出python代码实现如下:
class Solution:
def countRoutes(self, locations: List[int], start: int, finish: int, fuel: int) -> int:
MOD = 1000000007
fuel_cost = [[abs(i - j) for j in locations] for i in locations]
n = len(locations)
@lru_cache(None)
def dp(loc, fuel):
if fuel < 0:
return 0
ans = 1 if loc == finish else 0
for i in range(n):
if i == loc:
continue
ans += dp(i, fuel-fuel_cost[loc][i])
return ans % MOD
return dp(start, fuel)
提交代码评测得到:耗时2040ms,占用内存39.1MB。
当前最优算法耗时360ms,看了一下,他的算法思路和我本质上是一样的,但是他就是使用了一般的动态规划方式,构建了一个 N × ( f u e l + 1 ) N \times (fuel+1) N×(fuel+1)的矩阵来保存中间计算结果。
如果感兴趣的读者可以自行研究一下,毕竟实话实说,使用缓存虽然实现起来方便很多,但一直觉得是邪道来着。。。>﹏<