代码随想录day2 977有序数组的平方 & 209长度最小的子数组 & 59螺旋矩阵II

977. 有序数组的平方 - 力扣(LeetCode)

由于数组有序,可以从两头开始(绝对值大)用双指针向中间(绝对值小)逼近,只遍历一次数组,时间和空间复杂度均为O(n),p指示当前元素在新数组中的下标。

class Solution(object):
    def sortedSquares(self, nums):
        l = 0
        r = len(nums) - 1
        p = len(nums) - 1
        res = [0] * len(nums)

        while p >= 0:
            if nums[l] ** 2 <= nums[r] ** 2:
                res[p] = nums[r] ** 2
                r -= 1
            else:
                res[p] = nums[l] ** 2
                l += 1

            p -= 1

        return res

209. 长度最小的子数组 - 力扣(LeetCode)

滑动窗口法,时间O(n)、空间O(1),l和r指针各自遍历一次数组即可。但边界条件判断易错。

以下代码是左闭右开,即子数组为[l, r)的写法:

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        n = len(nums)
        l = 0
        r = 0
        min_len = n + 1
        cur_sum = 0

        while r <= n: #边界条件判断易错点1
            while cur_sum >= target:
                min_len = min(min_len, r - l) #边界条件判断易错点2
                cur_sum -= nums[l]
                l += 1
            if r < n: #边界条件判断易错点3:防止下标超出范围
                cur_sum += nums[r]
            r += 1

        return min_len if min_len <= n else 0

易错点1:若写成 while r < n,可能会在 cur_sum 刚加上 nums[-1] 时结束循环,错过对这个新的子数组的左边界更改(错过第二个while循环)。

易错点2:由于左闭右开,子数组长度为 r - l。

易错点3:由于最外层是 while r <= n,为避免下标超出范围,需多加一个判断。

以下为左闭右闭,即子数组为 [l, r]的写法,该写法更简洁、不易出错:

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        n = len(nums)
        l = 0
        r = 0
        min_len = n + 1
        cur_sum = 0
        
        while r < n: #右边界r最大取到n-1,即nums最后一个元素下标
            cur_sum += nums[r] #先在cur_sum加上右边界的值,得到新的子数组[l,r]
            
            while cur_sum >= target: #若达到target,更新数组的左边界
                min_len = min(min_len, r - l + 1) #右边也是闭合的,因此数组长度r-l+1
                cur_sum -= nums[l]
                l += 1
            
            r += 1 #当cur_sum小于target,更新右边界

        return min_len if min_len <= n else 0

59. 螺旋矩阵 II - 力扣(LeetCode)

时间、空间 O(n^2) & O(n^2)

import numpy as np

class Solution:
    def generateMatrix(self, n: int):
        mat = np.zeros((n, n), dtype = int) 
        #注意x,y虽然是直觉上的横纵坐标,但x作为列idx,是mat的第1维;y作为行idx,是mat的第0维
        x = 0
        y = 0
        xnew = 0
        ynew = 0
        direct = 0
        i = 1
        while i <= n ** 2: 
            if self.valid(xnew, ynew, n) and mat[ynew][xnew] == 0: #如果未超出边界而且未访问过
                x, y = xnew, ynew #是有效的新坐标,赋值给x、y
                mat[y][x] = i
                xnew, ynew = self.move(direct, x, y)
                i += 1 #只有当坐标有效、给mat[y][x]赋值后再考虑下一个i
            else:
                direct = (direct + 1) % 4 #顺时针转向:右->下->左->上->右
                xnew, ynew = self.move(direct, x, y) 

        return mat.tolist() #二维np数组转为list[list[]]

    def move(self, direct: int, x: int, y: int):
        if direct == 0:
            return [x + 1, y]
        if direct == 1:
            return [x, y + 1]
        if direct == 2:
            return [x - 1, y]
        if direct == 3:
            return [x, y - 1] 
        
    def valid(self, x: int, y: int, n: int) -> bool:
        if x >= 0 and x < n and y >= 0 and y < n:
            return True
        else:
            return False

易错点1:若这样初始化二维数组,将不能独立地更改数组中的元素,因此需要使用numpy数组。

mat = [[0] * n] * n 
#或者
mat = []
tmp = [0] * n
for _ in range(n): #time: O(n)
    mat.append(tmp)

易错点2: move()函数得到的新坐标不一定有效,若无效需要顺时针转向再重新生成新坐标,因此横纵坐标各需要维护两个变量。

 易错点3:x,y虽然是直觉上的横纵坐标(在写move函数时),但x作为列idx,是mat的第1维;y作为行idx,是mat的第0维(在用下标访问二维数组元素时)。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值