代码随想录|977.有序数组平方;209,长度最小子数组;59,螺旋矩阵

有序数组的平方

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

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

关键词:非递减序列,平方。 那么我们可以指导最大值应该属于两端的中的其中一个,而得到的新序列需以非递减排序,所以得到的最大值应该位于最右边。

Python 代码

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

注:python 代码中,result = nums 是变量的引用,也就是对于result的改动也会同样作用于nums,所以在初始化一个变量的时候,需要注意是否需要引用。

长度最小数组

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

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

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

关键词:正整数,长度最小,连续子数组。

滑动窗口可行性:

第一次接触滑动窗口,我产生了这样的疑问:这样的遍历是否考虑到了所有的情况?是否可行?这里就先简要阐述一下滑动窗口的可行性。为了方便,这里将左右指针简写为 i 和 j 。

首先注意到该数组元素都为正整数,那么就是区间和满足某种意义上的单调性,因而会有一下两个特性:

  1. 若区间[ i , j ] 满足加和大于等于 target, 则任何包含此区间的区间都满足加和大于等于target。也即 i 往左或者 j 往右扩张的区间都满足加和大于等于target。我们称区间[ i , j ]加和大于等于target为充分条件,区间[ i , j ] 为充分区间。
  2. 若区间[ i , j ]加和小于target,则任何被此区间包含的区间加和都小于target。

由于这两条性质,我们可以将暴力求解中的嵌套循环简化为滑动窗口。

这里将 j 作为外层循环变量,i 作为内层循环变量,且都是从左往右循环。在 j 向右遍历的过程中,每一次遍历首先考虑该次遍历中最大窗口,若最大区间不是充分区间,则没有必要考虑更小的区间,即将 i 向右移动;若最大区间是充分区间,则不需要将 i 往左移动。这里的最大区间并不全是指 [ 0 , j ]。若是 j 的遍历中,若是还没有出现过充分区间,那么 [ 0 , j ] 为最大区间。但是如果某一次遍历出现了充分区间,并且移动了 i 后,此时的 i 将作为 j + 1 最大区间的起始点。当然 [ i , j +1] 可能不是充分区间,不满足性质一,理应考虑将 i 往左移动的情况,但是这题需求最小区间,将 i 往左移的区间长度就会大于上个出现的充分区间,因而我们也不考虑将 i 往左移动。 这样一来,我们就有了滑动窗口。

理解:

滑动窗口右指针是为了放大窗口,从强往弱找到满足条件的窗口;左指针是为了缩小窗口,在所有满足条件的窗口中找到最优的窗口。

python 代码

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        i,result = 0,len(nums)+1
        sums = 0
        for j in range(len(nums)):
            sums = sums + nums[j]
            while sums >= target:
                result = min(result,j-i+1)
                sums -= nums[i]
                i += 1
        return result if result != len(nums) +1 else 0

注:左指针在移动的时候应该考虑循环而不是if 条件语句,因为i移动一位区间可能仍然加和大于等于target。

螺旋矩阵

题目链接:力扣

题目描述:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

思路:螺旋矩阵需要考虑到一圈一圈的循环,但是每一圈循环里面可以嵌套另一个循环。循环不变量即在循环之中不变的量,不一定得是某个变量,也可以是方程,规则等。这里就把填补规则作为不变量,也就是每一次循环填补边长减一个元素,那么这样四条规则都一样了,这就使得循环更不容易出错。

注:循环次数:每次循环填补两行两列,因此外循环应该有 (n//2) 次。 

python 代码

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:      
        startx,starty = 0,0
        count = 1
        offset = 1
        result = [[0] * n for _ in range(n)]
        while (n - 2*offset >= 0 ):
            for j in range(startx,n-offset):
                result[startx][j] = count
                count += 1
            for i in range(starty,n-offset):
                result[i][j+1] = count
                count += 1
            for j in range(n-offset,startx,-1):
                result[i+1][j] = count
                count += 1
            for i in range(n-offset,starty,-1):
                result[i][j-1] = count
                count += 1
            offset += 1
            startx += 1
            starty += 1
        if n%2 == 1:
            result[n//2][n//2] = n **2
        return result 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值