leetcode算法刷题2

嗨,大家好,我是心海

这是算法刷题系列第 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%,我们代码有两层循环,时间复杂度O(n^2),那该如何优化?

优化如下

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步生成中国风/赛博朋克海报

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值