嗨,大家好,我是心海
这是算法刷题系列第 2 篇文章
这个系列主要是记录一下刷题的过程
也激励自己坚持刷题下去,大概每篇文章记录 1 到 3 题,以七天为周期
这是第一个七天第 2 篇文章
我们从简单的题目开始
一、力扣3427. 变长子数组求和
题目
我们先根据题目要求,编写一个简单的代码
class Solution:
def subarraySum(self, nums: List[int]) -> int:
sum=0
for i in range(len(nums)):
st=max(0,i-nums[i])
for j in range(st,i+1):
sum+=nums[j]
return sum
提交发现,时间一点慢了,才击败 13%,我们代码有两层循环,时间复杂度,那该如何优化?
优化如下
class Solution:
def subarraySum(self, nums: List[int]) -> int:
# 构建前缀和数组,s[i+1] 是 nums[0..i] 的和
s = list(accumulate(nums, initial=0))
ans = 0
for i, num in enumerate(nums):
# 计算子数组起始位置 start
start = max(i - num, 0)
# 利用前缀和计算子数组和并累加
ans += s[i + 1] - s[start]
return ans
其中,accumulate(nums, initial=0)
生成一个前缀和数组 s,并且第一个元素值为 0
initial=0
让 s[0] = 0
,后续 s[i+1]
表示 nums[0..i]
的元素和。例如,nums = [2, 3, 1]
,则 s = [0, 2, 5, 6]
。
对于每个下标 i
,对应子数组为 nums[start..i]
(start = max(0, i - nums[i])
)。利用前缀和,该子数组的和为 s[i+1] - s[start]
。遍历所有 i
,累加这些和,即可得到最终结果。
现在时间复杂度为 O(n),速度也就快了很多
二、力扣3065. 超过阈值最少操作次数
题目
这道题很简单,本质就是问数组中多少个数比k小
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
count=0
for i in range(len(nums)):
if nums[i]<k:
count+=1
return count
时间复杂度 O(n),空间复杂度O(1)
这么简单的题目肯定还有更优雅的解法
return sum(x < k for x in nums)
这里需要注意的就是python中 true 为1,false 为 0
三、力扣3248. 矩阵中的蛇
题目
这道题也不难,主要分析好每一个格子对应的值,与 n 的关系即可
class Solution:
def finalPositionOfSnake(self, n: int, commands: List[str]) -> int:
i, j = 0, 0 # 初始化蛇的位置坐标,对应矩阵的 (i, j)
for cmd in commands:
if cmd == "RIGHT":
j += 1
elif cmd == "LEFT":
j -= 1
elif cmd == "DOWN":
i += 1
elif cmd == "UP":
i -= 1
return i * n + j
同样,时间复杂度 O(n),表现较好,但是消耗内存还是比较大
根据力扣其它答友的答案(@灵茶山艾府),空间复杂度方面得到进一步优化
class Solution:
def finalPositionOfSnake(self, n: int, commands: List[str]) -> int:
i = j = 0
for s in commands:
match s[0]:
case 'U': i -= 1
case 'D': i += 1
case 'L': j -= 1
case _: j += 1 # 匹配其他任意值,相当于 switch 中的 default
return i * n + j
结语
力扣算法刷题栏目,是记录下博主个人解答过程,所以不一定是最好的、唯一的答案,更多优秀题解可以参考官方答案
如果这篇文章对你有所启发,期待你的点赞关注!
精彩推荐
不会PS也能做设计?谷歌Gemini保姆教程:4步生成中国风/赛博朋克海报