算法训练营DAY2_有序数组的平方、长度最小的子数组、螺旋矩阵II

本文介绍了如何使用双指针法解决LeetCode中的977.有序数组的平方和209.长度最小的子数组问题。在有序数组的平方问题中,通过双指针从两端开始比较并填充结果数组。而在长度最小的子数组问题中,利用滑动窗口的思想,保持子数组和大于等于目标值,不断移动窗口边界以找到最小子数组。此外,还讨论了螺旋矩阵II的模拟实现。这些方法展示了双指针和滑动窗口在数组问题中的应用。
摘要由CSDN通过智能技术生成

LeetCode | 977.有序数组的平方

题目

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

977.有序数组的平方https://leetcode.cn/problems/squares-of-a-sorted-array/

思考

  • 一开始思考解决的时候,没有想到如何处理负数平方后变大的情况,使得“0”会卡在一众数字中间;
  • 后面想到数组可能有负数,所以在平方后呈现出的是两头大、中间小的情况,因此可以运用双指针法,从两头开始比较大小,依次取出放入最终数组中;

题解: 

 1.第一种写法(for循环)

// 解法一
var sortedSquares = function(nums) {
    // 设置两个指针
    let right = nums.length - 1;
    let left = 0;
    // 新数组
    let newArr = new Array()
    for(let i = nums.length - 1; i >= 0; i--){
        if(nums[left]*nums[left] < nums[right]*nums[right]){
            newArr[i] = nums[right]*nums[right];
            right--;
        }else{
            newArr[i] = nums[left]*nums[left];
            left++;
        }
    }
    return newArr
}

 2.第二种写法(while循环)

// 解法二(小小的理解不同,区别不大)
var sortedSquares = function(nums) {
    // 创建一个新数组
    let newArr = new Array()
    let i = nums.length -1;
    let left = 0;
    let right = nums.length -1;
    while(left <= right){
        if(nums[left]*nums[left] - nums[right]*nums[right] < 0){
            newArr[i--] = nums[right]*nums[right]
            right--;
        }else{
            newArr[i--] = nums[left]*nums[left]
            left++;
        }
    };
    return newArr
};

双指针法思路总结:

  • 第27题移除元素也使用了双指针法,将两个指针放在同侧,一快一慢,慢指针用于记住位置,快指针用于寻找新的元素;
    • 而这道题是将两个指针放在了两侧,将两个指针同时进行比较,符合条件的先取出;
    • 如在这道题中将两个指针放在同侧,那么将多许多比较的次数,并且容易出现错漏;
  • 目前看来,我认为在需要进行比较时可以考虑双指针,同时想一想需要比较的模型形状,从而确定指针放的位置;

LeetCode | 209.长度最小的子数组

题目

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

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

思考

  • 没有接触过滑动窗口思想,题也见得少,一看到这道题完全懵了,困惑我的有:
    • 什么叫连续子数组?必须要每个元素的值是连续的吗?
    • 怎么筛选得出来所有大于等于target的数组,然后再比较它们呢?
  • 看了两边视频过后,还是有疑惑:
    • 为什么for+while的组合却降低了时间复杂度?
    • 真的能确保筛查不漏吗?
  • 最后画了图才想明白,只能说妙啊;

题解

var minSubArrayLen = function (target, nums) {
    // let result = Number.MAX_VALUE;
    let result = nums.length + 1;
    let sum = 0;
    // 设置起始指针
    let i = 0;
    // 设置终止指针
    for(let j = 0; j < nums.length; j++){
        sum += nums[j];
        while(sum >= target){
            let sumL = j - i + 1;
            result = Math.min(result, sumL);
            sum -= nums[i];
            i++;
        }
    }
    // 注意当没有符合条件的情况下,需要返回0
    if(result == nums.length + 1){
        return 0
    }else{
        return result
    }
}

滑动窗口思路总结:

  • 是双指针法的一种,相比于之前两道双指针法的题,这道题是使两个指针中间的“窗口”保持满足≥target的状态,然后进行移动;
  • 与暴力解法的两次for循环相比,一个元素只用被操作进去和出去的两次,所以时间复杂度是O(2n)→O(n);

LeetCode | 59.螺旋矩阵II

题目

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

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

思考

  • 没有接触过的类型,并且对于二维数组之前也不清楚;
  • 了解后知道是一道模拟题,并且总体难度不大,只是要注意不要被绕晕,写清楚判断条件;

题解

var generateMatrix = function(n) {
    // 设置初始位置坐标
    let startX = startY = 0;
    // 设置循环的圈数
    let loop = 1
    let count = 1
    // 创建二维数组
    let nums = new Array(n).fill(0).map(()=>new Array(n).fill(0))
    // 只要循环的圈数小于n/2,就要继续循环
    while(loop <= n/2){
        let i = startX;
        let j = startY;
        // 第一条边
        for(; j < n - loop; j++){
            nums[startX][j] = count++
        }
        // 第二条边
        for(; i < n - loop; i++){
            nums[i][j] = count++
        }
        // 第三条边
        for(; j > startY; j--){
            nums[i][j] = count++
        }
        // 第四条边
        for(; i > startX; i--){
            nums[i][startY] = count++
        }
        // 一圈循环后
        startX++;
        startY++;
        loop++;
    }
    // 如果是单数圈
    if(n % 2 == 1){
        nums[startX][startY] = count
    }
    return nums
}

思路总结:

  • 坚持循环不变量原则;
  • 找对方法进行遍历,不要把自己绕进去了;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值