代码随想录|Day02|数组02|977. 有序数组的平方、209. 移长度最小的字数组、59. 螺旋矩阵II

977. 有序数组的平方

暴力:平方每个元素,然后排序,时间复杂度取决于排序算法。

思路:有效利用题干中的“非递减数组”,意味着较大值在数组右端,有以下两个观察:

1. 若不含负数,平方后数组的较大值依然在右端。

2. 若包含负数,平方后数组的较大值在左端或右端,呈山谷状。

由于平方后较大值一定在两端,因此使用双指针从两端向中间遍历,每次取较大值插入新开辟的数组。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:

        left, right = 0, len(nums) - 1

        result = [float('inf')] * len(nums)

        index = len(nums) - 1
        # 为什么不是 left < right ?
        # 设想还剩最后两个元素 a,b
        # 对比后将 a。赋值给 result
        # 此时 left 移动,与 right 重合,跳出循环,b 即被遗漏
        while left <= right:

            if nums[left] ** 2 < nums[right] ** 2:
                result[index] = nums[right] ** 2
                right -= 1
            # nums[left] == nums[right]的情况下,给result赋值任意一个都行,所以和其他两种情况合并
            else:
                result[index] = nums[left] ** 2
                left += 1
            index -= 1

        return result
# 时间复杂度:
# O(n)

209. 长度最小的子数组

暴力:两层for循环遍历所有子数组,过程维护一个满足条件的最小长度,O(n²)

思路:实际上,当找到一个符合条件的子数组, 不需要再去判断任何更长的子数组。

我们使用双指针来维护一个滑动窗口,左右指针指向第一个元素,右指针先行,直到找到一个满足条件的窗口,此时只需要寻找更短的窗口,通过移动左指针缩小窗口,维护一个 min_len。当窗口缩小到不满足条件的时候,再次移动右指针,也就是重复此过程。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:

        cur_sum = 0
        left, right = 0, 0
        min_len = float('inf')

        while right < len(nums):
            
            cur_sum += nums[right]
            # 当找到符合条件的窗口,不断移动左指针来缩小窗口,直至不符合条件
            while cur_sum >= target:
                min_len = min(min_len, right - left + 1)
                cur_sum -= nums[left]
                left += 1
            
            right += 1
        # 循环结束后,有可能不存在符合条件的子数组
        # 此时 min_len 未被更新,保持 float('inf') 的初始化状态
        # 根据题干,需返回 0
        return min_len if min_len != float('inf') else 0
# 时间复杂度:
# 每个元素都会进出一次窗口
# O(2n) = O(n)

59. 螺旋矩阵II

模拟题,考察代码掌控能力,多练多记吧!

本题的关键是,起始点 startxstarty、边界 n - offset ,以及填充顺序的理解。

具体注释放在了代码相应位置,以供辅助理解。

模拟过程:

填充第一行:行不变(startx),     列变化(starty -> n - offset)

填充第三列:列不变(n - offset),行变化(startx -> n - offset)

填充第三行:行不变(n - offset),列变化(n - offset -> starty)

填充第一列:列不变(starty),     行变化(n - offset -> startx)

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        # 创建矩阵
        matrix = [[0] * n for _ in range(n)]
        startx, starty = 0, 0
        # mid用来针对n为奇数时,矩阵存在一个中心点,需要手动更新
        loop, mid = n // 2, n // 2
        count = 1

        for offset in range(1, loop + 1):
            # 上行,左至右
            # x 不动,保持在 startx
            # 移动 y,从 starty 至 n - offset
            for i in range(starty, n - offset):
                matrix[startx][i] = count
                count += 1
            # 右列,上至下
            # y 不动,保持在 n - offset
            # x 移动,从 startx 至 n - offset
            for i in range(startx, n - offset):
                matrix[i][n - offset] = count
                count += 1
            # 下行,右至左
            # x 不动,保持在 n - offset
            # y 移动,从 n - offset 至 starty
            for i in range(n - offset, starty, -1):
                matrix[n - offset][i] = count
                count += 1
            # 左列,下至上
            # y 不动,保持在 starty
            # x 移动,从 n - offset 至 startx
            for i in range(n - offset, startx, -1):
                matrix[i][starty] = count
                count += 1
            # 一圈更新完成,朝内部offset一圈
            startx += 1
            starty += 1
        # 如果n为基数,会存在一个单独的中心点,需要手动更新
        if n % 2 != 0:
            matrix[mid][mid] = count
        return matrix
# 时间复杂度:
# 为n²个元素赋值一次
# O(n²)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值