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

977.有序数组的平方

题目建议: 本题关键在于理解双指针思想

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章讲解:https://programmercarl.com/0977.有序数组的平方.html
视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep

思考

存在非负数,平方之后相当于是一个开口向上的抛物线,最小值在中间,通过左右两个指针以此比较两端的大小,逐渐逼近中间的最小值。
注意 python list的.sort和.reverse操作返回的不是改变后的list。list本身会改变。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        # 左右指针向中间靠拢
        i = 0 
        j = len(nums) - 1
        res = []
        while i <= j :
            if nums[i]**2 < nums[j]**2:
                res.append(nums[j]**2)
                j-=1
            else:
                res.append(nums[i]**2)
                i+=1
        res.reverse()
        return res

209.长度最小的子数组

题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。 拓展题目可以先不做。

题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
文章讲解:https://programmercarl.com/0209.长度最小的子数组.html
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE

思考

1个多月前刷过这道题,又快忘了,想了20分钟才有点思路。代码写起来容易出错,尤其是if和while嵌套,什么时候用if,什么时候用while容易错乱。
下面的写法之所以长度为j-i,是因为sum_num+=nums[j]放在了while里,满足条件退出时,j多加了1

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # i j 表示滑动窗口的左右边界
        # 窗口内的数之和小于target时,j++,大于target时,i++
        i = 0
        j = 0
        sum_num = 0 
        min_len = 10000000000
       
        while j < len(nums):
            while (sum_num < target and j < len(nums)):
                sum_num+=nums[j]
                j+=1
            while (sum_num >= target and i <= j):
                #print(i,j)
                if j-i < min_len:
                    min_len = j-i
                sum_num-=nums[i]
                i+=1
            
        #print(sum_num)
        if min_len == 10000000000:
            return 0
        return min_len

这个是之前的写法。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        i = 0 
        j = 0
        n = len(nums)
        sum_num = 0
        min_res = 10000000
        while j < n:
            sum_num+=nums[j]
            if sum_num<target:
                j+=1
            else:
                while sum_num >= target:
                    min_res = min(min_res,j-i+1)
                    sum_num = sum_num - nums[i]
                    i+=1
                j+=1
        if min_res  == 10000000:
            min_res = 0
        return min_res

其中if sum_num<target的判断条件可以合并在下面的while里,精简后的代码如下

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        l = len(nums)
        left = 0
        right = 0
        min_len = float('inf')
        cur_sum = 0 #当前的累加值
        
        while right < l:
            cur_sum += nums[right]
            
            while cur_sum >= s: # 当前累加值大于目标值
                min_len = min(min_len, right - left + 1)
                cur_sum -= nums[left]
                left += 1
            
            right += 1
        
        return min_len if min_len != float('inf') else 0

59.螺旋矩阵II

题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。

题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
文章讲解:https://programmercarl.com/0059.螺旋矩阵II.html
视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/

思考

跟算法关系不大,但是很考验边界条件的控制。本题通过左闭右开区间定义进行实现。
注意 python二维数组的初始化。通过l和r来定义遍历区间。因为是左闭右开,所有控制条件是l<r。(l=r时,取不到值了),所以如果n为奇数,最后会遇到l=r,就是最中间的数,需要单独处理一下。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix  = [[0] * n for i in range(n)]
        # 区间定义
        l = 0 
        r = n-1
        index = 1
        while l < r:
            #初始化起点
            i = l
            j = l
            #->
            while j < r:
                matrix[i][j] = index
                index+=1
                j+=1
            #↓
            while i < r:
                matrix[i][j] = index
                index+=1
                i+=1
            #<-
            while j > l:
                matrix[i][j] = index
                index+=1
                j-=1
            #↑
            while i > l:
                matrix[i][j] = index
                index+=1
                i-=1
            # 下一圈
            l+=1
            r-=1
        if n%2 == 1:
            #中间的数
            i = int(n/2)
            matrix[i][i] = index
        return matrix
posted @ 2024-05-24 00:25  forrestr  阅读(29)  评论(0)    收藏  举报