算法第二天|LC-997,209,59 数组专题

前言

打卡第二天,加油!


有序数组的平方

977. 有序数组的平方icon-default.png?t=N7T8https://leetcode.cn/problems/squares-of-a-sorted-array/

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

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 已按 非递减顺序 排序

方法1:暴力法

将原数组中元素全部取平方并写入,再使用一次排序算法

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            nums[i] = nums[i] * nums[i]
        nums.sort()
        return nums

方法二:双指针法

题目中因为有负数存在,且非递减排序,所以平方的最大值只能在列表的最左边或者最右边

所以设置两个指针,一个指向最左边,一个指向最右边,并且新建一个同样大小的列表result用来存放平方后的数据

如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。

如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i]; 。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left = 0
        i, right = len(nums) -1, len(nums) -1
        res = [float('inf')] * len(nums) # 需要提前定义列表,存放结果

        while left <= right:
            if nums[left]**2 >= nums[right]**2:
                res[i] = nums[left]**2
                left+=1
            else:
                res[i] = nums[right]**2
                right-=1
            i-=1
        return res

此时的时间复杂度为O(n),相对于暴力排序的解法O(n + nlog n)还是提升不少的。

长度最小的子数组

209. 长度最小的子数组icon-default.png?t=N7T8https://leetcode.cn/problems/minimum-size-subarray-sum/

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

1.暴力法

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        for k in range(len(nums)):
            if nums[k] == target:
                return 1
        temp = 0
        for i in range(len(nums)):
            count = 0
            sum = 0
            for j in range(i,len(nums)):
                sum = sum + nums[j]
                count+=1
                if (target <= sum):
                    if temp == 0:
                        temp = count
                    elif temp > count:
                        temp = count
                    break
        
        return temp

当数额庞大时候会超时,故不可使用

滑动窗口法

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

暴力解法使用两个for循环

滑动窗口使用一个for循环,先从第一个元素开始累加,知道大于等于target出现,此时for循环指针先不变动,开始移动左指针,并且将累加的值结果中减去left指针移动前所指向的元素值,如果此时sum的值任然大于等于target则继续移动左指针,否则将目前最小长度赋予全局变量,然后继续for循环。

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = 0
        sum = 0
        result = float('inf')
        for i in range(len(nums)):
            sum += nums[i]
            while(sum >= target):
                sum -= nums[left]
                min_len = i - left +1
                result = min(min_len,result)
                left +=1

        return result if result != float('inf') else 0

螺旋矩阵 II

59. 螺旋矩阵 IIicon-default.png?t=N7T8https://leetcode.cn/problems/spiral-matrix-ii/

坚持循环不变量原则

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0]*n for _ in range(n)]
        start_x ,start_y = 0, 0
        loop, mid = n //2 , n //2
        count = 1

        for offset in range(1,loop+1):
            for i in range(start_y,n - offset):
                nums[start_x][i] = count
                count += 1
            for i in range(start_x, n - offset):
                nums[i][n-offset] = count
                count += 1
            for i in range(n-offset,start_y,-1):
                nums[n-offset][i] = 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

        if n % 2 != 0:
            nums[mid][mid] = count
        return nums

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值