代码随想录算法训练营第二天 | Leetcode 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵II | 数组、双指针、滑动窗口、二维数组、模拟矩阵生成

题目:977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

涉及数据结构
  • 数组
我的思路
  • 顺序计算每个元素平方,再对新数组进行排序
  • 排序可以结合双指针的用法,但没想到是两端向中间,思路不同 直接开看算法视频
  • P.S. 快速排序等排序方法照样可做 nums.sort()
解法
题目前提
  • 有序数组,最大值从两边取到
双指针思路
  • 每次循环内对两端值判断,取较大值

  • 新数组下标由大到小更新

  • 时间复杂度: O ( n ) O(n) O(n)

  • 双指针

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:         
        left = 0
        right = len(nums) -1
        res_nums = [float(inf)] * len(nums) 
        res_index = len(nums) -1

        while left <= right :
            if nums[left]*nums[left] > nums[right]*nums[right] :
                res_nums[res_index] = nums[left]*nums[left]
                res_index -= 1
                left += 1
            else:
                res_nums[res_index] = nums[right]*nums[right]
                res_index -= 1
                right -= 1

        return res_nums
效果、心得:
  • 双指针用起来不难用,但是下标更新的方式需要多看变形题,还要多注意比较更新时出现覆盖问题(什么时候需要新建数组)

题目:209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0

涉及数据结构
  • 数组
我的思路
  • 类似双指针 外层 for 用来遍历 left ,内层 for 用来遍历 right
  • 结果:超时
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        res_len = []
        for left in range(0, len(nums)):

            # print('left = ', left,)

            temp_sum = 0

            for right in range(left, len(nums)):
                # print('right = ', right)
                temp_sum = sum(nums[left:right+1])
                # print('temp_sum = ', temp_sum)

                if temp_sum >= target:
                    res_len.append(right - left + 1)
                    break

            # print ('inner loop right = ', right)
            # print('res_len = ', res_len)
        # print('at last res_len = ', res_len)

        if len(res_len) != 0:
            return min(res_len)
        else:
            return 0
解法
题目前提
  • 正整数数组
  • 两层循环会超时
滑动窗口思路
  • 同样用双指针

  • 不断的调节子序列的起始位置和终止位置

  • 暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程

  • 一个循环里:j表示终止位置

  • 关键:如何移动起始位置 i → 当窗口中所有元素值 ≥ target时,滑动 i

  • 时间复杂度: O ( n ) O(n) O(n)

  • 自写超时

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        res = float(inf)
        left = 0
        for right in range(0, len(nums)):

            while sum(nums[left:right+1]) >= target:
                temp = right - left + 1 # 应该是这里多了一个sum的时间复杂度
                res = min(temp, res)
                left += 1
        if res != float(inf):
            return res
        else:
            return 0
  • 矫正
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        res = float(inf)
        left = 0
        cur_sum = 0

        for right in range(0, len(nums)):
            cur_sum += nums[right]

            while cur_sum >= target:
                res = min(right - left + 1, res)
                cur_sum -= nums[left]
                left += 1
                
            return res if res != float(inf) else 0
效果、心得:
  • 本质还是双指针,但这种谁fast谁slow,或者left在哪right又定义在哪,需要多看变形题找感觉

题目:59. 螺旋矩阵II

给你一个正整数 n ,生成一个包含 1n^2 所有元素,且元素按顺时针顺序螺旋排列n x n 正方形矩阵 matrix

涉及数据结构
  • 二维数组
我的思路
  • 盲区,直接开看视频讲解
解法
题目前提
  • 正整数数组、升序
  • 方阵
模拟转圈【模拟题】
  • 边界处理需要注意
  • 循环不变量原则:对每条边的处理规则要统一
  • 转圈数: n / 2 n/2 n/2,若 n 是单数,直接对 nums[(n-1)/2][(n-1)/2] 赋最大值
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 定义起始位置,每圈改变当前的起始位置
  • 过程:
    • 圈数
    • 每圈起始位置更新
    • 每圈边界值更新
    • 每圈4条边怎么for
  • py语法注意:如果要使用列表创建一个二维数组,可以使用生成器来辅助实现;或者用numpy
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0 for i in range(n)] for j in range(n)]
        cir_num = n // 2
        start_x, start_y = 0, 0
        offset, count = 1, 1

        while cir_num :
            for j in range(start_y, n - offset) :
                nums[start_x][j] = count
                count += 1
            for i in range(start_x, n - offset) :
                nums[i][n - offset] = count
                count += 1
            for j in range(n - offset, start_y, -1) : 
                nums[n - offset][j] = count
                count += 1
            for i in range(n - offset, start_x, -1) :
                nums[i][start_y] = count
                count +=1
            
            start_x += 1; start_y += 1
            offset += 1; cir_num -= 1

        if n%2 == 1:
            nums[(n-1)//2][(n-1)//2] = n*n
        
        return nums
效果、心得:
  • 搞懂了怎么顺时针打印方阵
  • 要扩展成非方阵的场景,类似题 54. 螺旋矩阵 有空可做
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值