LeetCode Day2|977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

题目链接:977. 有序数组的平方 - 力扣(LeetCode)

思路:

对于此题第一反应是可以先做平方再进行排序,便有了以下暴力解法思路,时间复杂度O(n²),事实证明此法不可取,在力扣上超时提交失败

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        size = len(nums)
        index = 0
        while index < size:    # 先进行平方操作
            n = nums[index]
            nums[index] = n ** 2
            index += 1
        index = 0
        for i in range(1, size):   # 使用两层嵌套完成冒泡排序
            j = i-1
            while j >= 0:
                if nums[j+1] < nums[j]:
                    n = nums[j]
                    nums[j] = nums[j+1]
                    nums[j+1] = n
                j -= 1
        return nums

于是经过学习,有了双指针法的思路,时间复杂度为O(n),思路是从两端开始,由于是非递减数组,平方后最大的数一定在两端,故用双指针分别指向两端,选取平方后较大的数依次填入数组

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left, right = 0, len(nums)-1
        n = right
        result = [-1] * len(nums)
        while left <= right:
            lm = nums[left] ** 2
            rm = nums[right] ** 2
            if lm > rm:
                result[n] = lm
                left += 1
            else:
                result[n] = rm
                right -= 1
            n -= 1
        return result

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

思路:

首先是暴力解法,双层for循环将整个数组遍历一,时间复杂度O(n²) 空间复杂度O(1)

其次是类似双指针的滑动窗口法,不断调节子数组的起始位置和终止位置,首先移动右侧的终止位置指针直到找到满足条件的子数组记录长度subL,再移动左侧起始位置指针缩小范围,若依然满足条件则更新子数组长度subL,若不满足条件则继续向右滑动终止指针,以此类推,此方法时间复杂度O(n) 空间复杂度O(1)

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        res = float("inf")   # 定义一个无限大的数
        Sum = 0     # 滑动窗口数值之和
        i = 0      # 滑动窗口起始位置
        for j in range(len(nums)):
            Sum += nums[j]
            while Sum >= s:
                res = min(res, j-i+1)
                Sum -= nums[i]
                i += 1
        return 0 if res == float("inf") else res

题目链接:59. 螺旋矩阵 II - 力扣(LeetCode)

思路:

遇到此类题目可以画图帮助思考,坚持循环不变量原则,模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈画下去,但对于每一条边都要坚持左闭右开或者左开右闭的原则,左闭右开如下图所示:

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        x, y = 0, 0                 # 行和列起始点
        z = 1               
        loop, mid = n // 2, n // 2  # 迭代次数,n为奇数时中心点的位置
        nums = [[0] * n for _ in range(n)]

        for offset in range(1, loop + 1):       # 每循环一次偏移量加1,偏移量从1开始
            for i in range(y, n - offset):      # 从左至右,左闭右开
                nums[x][i] = z
                z += 1
            for i in range(x, n - offset):      #从上至下
                nums[i][n - offset] = z
                z += 1
            for i in range(n - offset, y, -1):  # 从右至左
                nums[n - offset][i] = z
                z += 1
            for i in range(n - offset, x, -1):  # 从下至上
                nums[i][y] = z
                z += 1
            x += 1                              # 更新起始点位置
            y += 1
        if n % 2 != 0:                          
            nums[mid][mid] = z

        return nums

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值