Day02

Day02 代码随想录刷题

知识点:双指针、滑动窗口、模拟

一、LeetCode977.有序数组的平方

1.解题思路

考点为双指针,据题意原数组nums是一个非递减、可能带负数的整数数组,所以每个元素平方后最大值肯定出现在数组两边,不是左边就是右边。

2.代码实现

我们通过双指针从两头向里搜索,找到平方后值最大的元素,再将该值存入新建的列表res中去(从后往前排)。

根据输入数组的长度len(nums)新建列表res,设计索引i,从后向前储存,实现res列表内元素的从小到大排列

列表两头元素nums[left]nums[right]平方后的值大小判断可以通过两者相加实现,相加后为正,则右侧元素平方后值更大;否则左侧的负数平方后值更大。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        # 双指针初始化
        left, right = 0, len(nums) - 1
        # 新建列表,内容初始化为 -1
        res = [-1]*len(nums)
        i = len(nums) - 1
        while left <= right:
            if nums[left] + nums[right] > 0:
                res[i] = nums[right]**2
                right -= 1
            else:
                res[i] = nums[left]**2
                left += 1
            i -= 1
        return res

该解法相当于遍历了一遍数组nums时间复杂度O(n),因为额外还维护了一个长度为n的结果数组res,所以空间复杂度也为O(n)

二、LeetCode209.长度最小的子数组

1.解题思路

考点为双指针实现滑动窗口,据题意可创建窗口右侧向右扩充,当窗口内元素满足要求后,窗口左侧开始向右收缩,期间找到满足要求的最小窗口长度min_len。当左侧窗口收缩导致窗口内元素不满足要求时,窗口会继续向右侧扩充,扩充与收缩依次循环,直至窗口右侧遍历完整个列表元素。

实质:

窗口不达标,右侧扩充;

窗口达标了,左侧收缩;

上述2条不断循环,期间保存最小窗口的长度,窗口右侧遍历完列表时结束循环

2.代码实现

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = right = 0 # 初始化窗口左右侧
        window_sum = 0 
        min_len = float("inf") # 窗口长度初始为无穷大

        while right < len(nums): # 设置循环中止条件
            window_sum += nums[right] 
            while window_sum >= target: # 窗口达标
                min_len = min(min_len, right - left + 1)
                window_sum -= nums[left]
                left += 1# 窗口左缩进

            right += 1# 窗口不达标,窗口右扩充
       
        if min_len == float("inf"):
            return 0
        else:
            return min_len

该解法额外设计了leftright两个指针,数组每个元素最多被操作2次,总共时间复杂度是2n,所以时间复杂度是O(n),因为额外维护了2个指针,空间复杂度是O(1)

三、LeetCode059.螺旋矩阵II

1.解题思路

考点为模拟,螺旋问题有规律,确定边界后用循环实现。循环需要找到循环不变量,即每次循环填充一圈,一圈有四边。最外层的边界索引为0n-1,我们每边只填充索引为0n-2的位置即可实现每次边填充规律都一样。

填充数组时还有规律:

假设循环填充多圈,每循环i圈(i0开始)后,每圈边界的填充索引开始点+i,终止点-i

每轮循环向右、向下填充的索引一样,只是横行列不同;向左,向上类似

向右填充时,行不变,行是上边界0,每循环i+i;列变化,索引由0n-1,每轮循环开始点+i,终止点-i

向下填充时,列不变,列是右边界n-1,每循环i-i;行变化,索引由0n-1,每轮循环开始点+i,终止点-i

向左填充时,行不变,行是下边界n-1,每循环i-i;列变化,索引由n-10,每轮循环开始点-i,终止点+i

向上填充时,列不变,列是左边界0,每循环i+i;行变化,索引由n-10,每轮循环开始点-i,终止点+i

输入n为奇数时,矩阵存在中心点,该值也需要补充

2.代码实现

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        # 确定循环圈数
        loop = n//2
        # 初始化结果矩阵:n*n的零矩阵
        res = [[0]*n for _ in range(n)]
        # 递增数num
        num = 1
        for i in range(0,loop):
            # i是循环轮数,a是每次边填充的索引
            for a in range(i,n - 1 - i):
                res[i][a] = num
                num += 1
            for a in range(i,n - 1 - i):
                res[a][n - 1 - i] = num
                num += 1
            for a in range(n - 1 - i, i, -1):
                res[n - 1 - i][a] = num
                num += 1
            for a in range(n - 1 - i, i, -1):
                res[a][i] = num
                num += 1
        # 奇偶判断是否需要补充中心值
        if n%2 == 1:
            res[loop][loop] = num

        return res

该解法模拟矩阵大小为n*n且需要全部遍历填充,所以时间复杂度O(n^2),此外还额外维护这个大小为n*n的矩阵,所以空间复杂度O(n^2)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值