代码随想录算法训练营Day2 | LeetCode977 有序数组的平方、LeetCode209 长度最小的子数组、LeetCode59 螺旋矩阵II

Posted by 慕念 on February 22, 2024

LeetCode977 有序数组的平方(双指针)

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/

文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html

视频讲解:https://www.bilibili.com/video/BV1QB4y1D7ep

重新构建一个平方后的数组之后,暴力调sort库函数,时间复杂度$O(nlogn)$:

class Solution(object):
    def sortedSquares(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        res=[]
        for i in nums:
            res.append(i*i)
        res.sort()
        return res

双指针法:

为什么想到双指针法:⭐题目特性

非递减顺序排序的含负数整数数组nums,平方后一定是数组两端大中间小:arrow_right:通过两端的两个指针的操作逐步向中间合拢,得到一个由大到小的数组(题目要求由小到大,新数组下标由大到小更新)

img

class Solution(object):
    def sortedSquares(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        k = len(nums) - 1 
        res = [0] * len(nums)

        i = 0   # 指向起始位置
       
        j = len(nums) - 1   # 指向终止位置
        
        while(i <= j):
            if(nums[i] * nums[i] > nums[j] * nums[j]):
                res[k] = nums[i] * nums[i]
                i += 1
            else:
                res[k] = nums[j] * nums[j]
                j -= 1   
            k -= 1             
        return res

时间复杂度为$O(n)$

LeetCode209 长度最小的子数组(滑动窗口)

题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/

文章讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html

视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE

暴力方法设置两个循环,时间复杂度$O(n^2)$,超时:

class Solution(object):
    def minSubArrayLen(self, target, nums):
        """
        :type target: int
        :type nums: List[int]
        :rtype: int
        """
        min_length = float('inf')  # 初始化为正无穷大
        
        for i in range(len(nums)):
            if nums[i] >= target:
                return 1
            current_sum = target - nums[i]
            j = i + 1
            length = 1  # 记录长度
            
            while j < len(nums):
                current_sum -= nums[j]
                length += 1
                if current_sum <= 0:
                    min_length = min(min_length, length)
                    break
                j += 1
        return 0 if min_length == float('inf') else min_length

image-20240222010250489

滑动窗口

⭐用一个for循环做两个for循环做的事情,for循环中的j是滑动窗口的终止位置

when移动窗口的起始位置?

->当我们发现集合里边的所有元素和大于等于S的时候,再去移动起始位置,就可以动态的去调整起始位置,来去收集不同的区间里边的和

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

class Solution(object):
    def minSubArrayLen(self, target, nums):
        """
        :type target: int
        :type nums: List[int]
        :rtype: int
        """
        i = 0	# 起始位置
        
        sum = 0
        result = float('inf')
        for j in range(len(nums)):	# j是终止位置
        
            sum += nums[j]
            while sum >= target:    # 持续移动
            
                subL = j - i + 1
                result = min(result, subL)
                sum = sum - nums[i] # 起始位置向后移动
                
                i += 1
        return result if result != float('inf') else 0

209.长度最小的子数组

以题目中的示例来举例,s=7, 数组是[2,3,1,2,4,3],最后找到[4,3]是最短距离。

LeetCode59 螺旋矩阵II

题目链接:https://leetcode.cn/problems/spiral-matrix-ii/

文章讲解:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html

视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/

⭐循环不变量:对每条边的处理规则一样(左闭右开)

img

class Solution(object):
    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """

        nums = [[0] * n for _ in range(n)]
        startx = 0
        starty = 0
        count = 1   # 计数
        
        loop, mid = n // 2, n // 2          # 迭代次数、n为奇数时,矩阵的中心点
        

        for offset in range(1, loop + 1) :      # 每循环一层偏移量加1,偏移量从1开始
        
            for j in range(starty, n - offset): # 上面一行
            
                nums[startx][j] = count
                count += 1
            for i in range(startx, n - offset): # 右边一列
            
                nums[i][n - offset] = count
                count += 1
            for j in range(n - offset, starty, -1): # 下面一行
            
                nums[n - offset][j] = count
                count += 1
            for i in range(n - offset, startx, -1): # 左边一列
            
                nums[i][starty] = count
                count += 1
            startx += 1         # 更新起始点
            
            starty += 1
        
        if n % 2 != 0 :			# n为奇数时,填充中心点
        
            nums[mid][mid] = count 

        return nums

⭐注意每次循环的边界和取值