DAY02算法学习| 977.有序数组的平方 , 209.长度最小的子数组, 59.螺旋矩阵II

977.有序数组的平方

977题目

题目描述:给定一个按非递减顺序排序的整数数组 nums,返回一个按非递减顺序排序的每个数字的平方数组。

Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Explanation: After squaring, the array becomes [16,1,0,9,100].
After sorting, it becomes [0,1,9,16,100].

Input: nums = [-7,-3,2,3,11] 
Output: [4,9,9,49,121]

Constraints:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums is sorted in non-decreasing order.

解题思路:

这个问题的关键在于如何有效地将输入数组中的每个元素平方并排序。由于输入数组已经按非递减顺序排序,我们可以利用这个性质来优化我们的解决方案。

解题的思路主要是使用双指针技术,一个从头开始,一个从尾开始。这是因为在有负数的情况下,平方后的最大值可能出现在数组的任一端。例如,[-4, -2, 0, 3] 平方后变为 [16, 4, 0, 9]。

注意: while(i<=j) 是为了确保处理输入数组的所有元素,包括当输入数组只有一个元素或者元素个数为奇数时的中间元素。

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

  1. 创建一个新的数组来保存结果,长度与输入数组相同。

  2. 设置两个指针,一个指向输入数组的开始(索引 i),一个指向输入数组的结束(索引 j)。同时设置一个指针 k 指向新数组的结束。

  3. 比较输入数组两端元素的绝对值,哪个大就将其平方放入新数组的对应位置(索引 k)。然后移动对应的指针(如果是左端元素大,就将 i 向右移动一位;如果是右端元素大,就将 j 向左移动一位)。无论哪种情况,都要将 k 向左移动一位。

  4. 重复第 3 步,直到 i 和 j 相遇。

复杂度:

  • 时间复杂度:由于我们只遍历一次数组,所以时间复杂度是 O(n),其中 n 是数组的长度。

  • 空间复杂度:我们使用了一个额外的数组来存储结果,其大小与输入数组的大小相同,因此空间复杂度是 O(n)。

209.长度最小的子数

209题目

题目描述:

给定一个正整数数组 nums 和一个正整数 target,返回 a 的最小长度
子数组 其总和大于或等于目标。 如果没有这样的子数组,则返回 0。

Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: The subarray [4,3] has the minimal length under the problem constraint.
Input: target = 4, nums = [1,4,4]
Output: 1
Input: target = 11, nums = [1,1,1,1,1,1,1,1]
Output: 0

解题思路:

这个问题是找出总和>=targe的最小连续子数组,所以比较适合用滑动窗口的方法来做。比如数组【1,5,3,2,4】,创窗两端在开始的时候都在第一个元素“1”那里,然后左端不动,右端一个一个的动(for x in range(len(nums)) ),当右端和左端之间的sum大于等于target的时候,计算出窗口长度,但是这道题是要找最小窗口,所以在满足sum的情况下我们把左端窗口向➡️移,看sum是否满足,如果满足就更新窗口长度,这道题为了能够持续更新窗口长度采用min(result,sub_len),为了一开始能够比较把result初始值设为float(“inf”)

注意最后一行代码的写法

 return 0 if result==float("inf") else result

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
         #slides window
        # start pointer: i, end pointer: j
        i=0
        sum=0
        result=float("inf")
        for j in range(len(nums)):
            sum+=nums[j]
            while sum>=target:
                sub_len=j-i+1
                result=min(sub_len,result)
                sum-=nums[i]
                i+=1
        return 0 if result==float("inf") else result
        

复杂度:

  • 时间复杂度:滑动窗口的方法只需遍历一次数组,所以时间复杂度是 O(n),其中 n 是数组的长度。

  • 空间复杂度:这个解决方案只使用了几个额外的变量,如 i、j、sum 和 result,这些变量的空间复杂度都是 O(1),也就是常数空间。所以,总的空间复杂度是 O(1)。

额外知识点:

在 Python 中,float("inf") 代表正无穷大。这是一种特殊的浮点数,表示一个非常大的值,大到任何其他的具体数值都无法超过它。

float("-inf") 代表负无穷大,表示一个非常小的值,小到任何其他的具体数值都无法小于它。

这两个值通常在需要对比找出最大值或最小值的情况下作为初始值使用。因为任何实际的数值都会比 float("-inf") 大,比 float("inf") 小,所以无论何时有一个实际的数值出现,都会替代这个初始值。

59.螺旋矩阵II

59题目

题目描述:

给定一个正整数 n,生成一个 n x n 矩阵,其中按螺旋顺序填充从 1 到 n**2 的元素。

  • 1 <= n <= 20

解题思路:

给定n,生成n*n的矩阵, 并把1到n**2的数值的数字,一圈一圈按照顺时针塞进矩阵。此时,选择排列数字的方法就很重要,想象一圈一圈的塞入数字。比如我们给定一个n等于4的矩阵,按照之前的方法我们可以走两圈。

先来看第一圈,每一个箭头走三个单位,也就是n-1, 每走一个坐标,此坐标对应的值加1,从(0,0)的一开始加。

以下是详细过程:

(0,0)-(0,2);x不变,y变大

(0,3)-(2,3);x变大,y不变

(3,3)到(3,1);x不变,y变小

(3,0)-(1,0);x变小,y不变

再来看第二圈

从(1,1)开始,然后循环一圈结束,可以看到如果n为偶数,则需要循环n//2 圈,如果为基数,循环完后再给最中心的值赋值。

代码:

定义每一圈开始的坐标,此题为0,0,等循环完一次再变值

定义循环次数,n//2

定义一个n*n矩阵:【【0】*n for _ in range(n)】

设置一个res代表对应值,走一次加一

设置edge:相当于一个边界,每次循环完右边界都会减一

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        #define the start coordinate
        start_x,start_y=0,0
        # for matrix have n edges, it should be take n//2 times loop
        looptime=0
        loops,mid=n//2,n//2
        #define a n*n matrix
        matrix=[[0]*n for _ in range(n)]
        res=1
        edge=1
        for looptime in range(1,loops+1):
            #left to right, walk distence is n-1
            for y in range(start_y,n-edge):
                matrix[start_x][y]=res
                res+=1

            #top-right to bottom-right
            for x in range(start_x,n-edge):
                matrix[x][n-edge]=res
                res+=1
        
             
            #right-bottom to left-bottom
            for y in range(n-edge,start_y,-1):
                matrix[n-edge][y]=res
                res+=1
              
            #bottom-left to top-left
            for x in range(n-edge,start_x,-1):
                matrix[x][start_y]=res
                res+=1
             
            # above is a whole loop, if we need more loop we should change the
            # we should change the start coordinate
            start_x+=1
            start_y+=1
            edge+=1
        if n%2!=0:
            matrix[mid][mid]=res
        return matrix



复杂度:

时间复杂度: 该代码使用嵌套循环来填充矩阵。外部循环运行了loops次,其中loopsn // 2。在每次循环中,有四个循环迭代当前循环的边缘。这些内部循环的迭代次数每次递减2。因此,内部循环的总迭代次数大约为(n-2) + (n-4) + ... + 2 = (n-2)*(n//2) = (n^2 - 2n) / 2。这给出了时间复杂度为O(n^2)。

空间复杂度: 该代码创建了一个n x n的矩阵来存储生成的值。因此,空间复杂度也是O(n^2)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值