阿锐刷题日记Day02-数组:双指针法解决 有序数组的平方 长度最小的子数组

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

建议大家先独立做题,然后看视频讲解,然后看文章讲解,然后在重新做一遍题,把题目AC,最后整理成今日当天的博客

拓展题目可以先不做

 详细布置

## 977.有序数组的平方 

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

题目链接:(https://leetcode.cn/problems/squares-of-a-sorted-array/)
文章讲解:(https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html)
视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep 


给你一个按 非递减顺序 排序的整数数组 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]


### 暴力解法
直接把所有的元素平方, 然后用库函数
```js
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    for (let i=0;i<nums.length;i++){
        nums[i]*=nums[i]
    }
    nums.sort((a,b)=>a-b)
    return nums
};
```

### 双指针法
观察可以发现, 原来的数组就是非递减的有序数组
然后不难发现, 从大到小就是从原数组的两边到中间, 所以适合用双指针
然后结果需要新开一个数组变量来接收
定义一个新数组result,和A数组一样的大小,让k指向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]; 。
```

```js
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let i=0,j=k=nums.length-1
    let res = Array(k).fill(0);
    while(i<=j){
        L=nums[i]**2
        R=nums[j]**2
        if(L<R){
            res[k]=R
            j--
        }else{
            res[k]=L
            i++
        }
        k--
    }
    return res
};
```

## 209.长度最小的子数组

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

题目链接:(https://leetcode.cn/problems/minimum-size-subarray-sum/)
文章讲解:(https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html)
视频讲解:(https://www.bilibili.com/video/BV1tZ4y1q7XE)


示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:
输入:target = 4, nums = [1,4,4]
输出:1

示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

用双指针来表示最小长度min_len, 就是r-l+1
快指针遍历数组累加里面的值为sum,看是否大于target,
只要大于target,就更新min_len, 快指针不动的情况下, 慢指针右移缩短长度, sum减去慢指针对应的数, 再判断是否大于target (这一行在一个循环内进行)

```js
/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
    len=nums.length
    l=r=sum=0
    min_len=Infinity
    while (r<len){
        sum+=nums[r]
        while(sum>=target){
            min_len=Math.min(min_len,r-l+1)
            sum-=nums[l]
            l+=1
        }
        r+=1
    }
    return min_len===Infinity?0:min_len
};
```
注意: 这里要先sum-=nums[l]然后再l+=1, 不然会导致nums减去的是错误的


## 59.螺旋矩阵II

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

题目链接:(https://leetcode.cn/problems/spiral-matrix-ii/)
文章讲解:(https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html)
视频讲解:(https://www.bilibili.com/video/BV1SL4y1N7mV/)

文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93%E7%AF%87.html 

这次主要参考GPT给的代码和动态图理解
![](assets/Pasted%20image%2020230612155054.png)
> - 每一个循环过后,边界都会移动,依次是蓝红紫黄朝中心移动,对应就是每一次循环的rowB+=1,colE-=1,rowE-=1,colB+=1
> - 因为range函数是左闭右开的,所以每次for i in的都是
> - range(begin,end+1)或者(end,begin-1,-1)
```python
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix = [[0 for i in range(n)] for j in range(n)] 
        # 创建一个n x n的矩阵,初始化为0
        rowBegin, rowEnd = 0, n-1 # 记录矩阵的行范围
        colBegin, colEnd = 0, n-1 # 记录矩阵的列范围
        num = 1 # 记录当前需要填充的数字
        while rowBegin <= rowEnd and colBegin <= colEnd:
            # 从左到右填充矩阵的第一行
            for i in range(colBegin, colEnd+1):
                matrix[rowBegin][i] = num
                num += 1
            rowBegin += 1
    
            # 从上到下填充矩阵的最后一列
            for i in range(rowBegin, rowEnd+1):
                matrix[i][colEnd] = num
                num += 1
            colEnd -= 1
    
            # 从右到左填充矩阵的最后一行
            if rowBegin <= rowEnd:
                for i in range(colEnd, colBegin-1, -1):
                    matrix[rowEnd][i] = num
                    num += 1
                rowEnd -= 1
    
            # 从下到上填充矩阵的第一列
            if colBegin <= colEnd:
                for i in range(rowEnd, rowBegin-1, -1):
                    matrix[i][colBegin] = num
                    num += 1
                colBegin += 1
    
        return matrix
```

#### 原理
创建一个大小为n x n的矩阵,并初始化所有元素为0。

定义四个指针:rowBegin、rowEnd、colBegin和colEnd,用于记录当前需要填充数字的行和列的范围。
初始化需要填充的数字num为1。
在每一轮循环中,按照从左到右、从上到下、从右到左、从下到上的顺序,依次填充矩阵的边界。

从左到右:遍历当前行的所有列,从colBegin到colEnd,将num赋值给对应位置的元素,然后将num加1。
从上到下:遍历当前列的所有行,从rowBegin+1到rowEnd,将num赋值给对应位置的元素,然后将num加1。
从右到左:需要先判断是否存在需要填充的行(rowBegin <= rowEnd),然后从colEnd-1到colBegin遍历当前行的所有列,将num赋值给对应位置的元素,然后将num加1。
从下到上:需要先判断是否存在需要填充的列(colBegin <= colEnd),然后从rowEnd-1到rowBegin遍历当前列的所有行,将num赋值给对应位置的元素,然后将num加1。

每填充完一圈边界后,更新指针的位置:rowBegin、rowEnd、colBegin和colEnd分别向内收缩,即分别加1、减1、加1、减1。
循环结束后,返回生成的矩阵。
这种四指针遍历的方法可以保证在顺时针螺旋填充矩阵时,每个数字都会按照正确的顺序被填充到对应的位置上。

### 总结 

题目建议:希望大家 也做一个自己 对数组专题的总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值