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

977. 有序数组的平方

原理

准备:双指针、一个空数组。双指针指向的两个元素作比较,更大的数平方之后,放入空数组的尾部空位。

图解

其实这题的指针有两种方法:

  • 从两边向中间靠拢,得到的是由大到小的值
  • 从中间向两边靠拢,得到的有由小到大的值

由于想直接得到由小到大的数组,所以我选择找到正负的分界线,然后left、right指针从中间开始,分别向两边走。

这样的方法不如left、right在0和nums.length-1的位置。

因为如果去到中间,left、right的初始位置、循环的终止条件终止条件都更难设置。

而选择left、right从两边向中间靠拢,相遇的时候停止就行,初始位置、终止条件都更好确定。

var sortedSquares = function(nums) {
    var arr = [];
    var index = nums.length - 1;
	// 这里的循环变量增减没有写在for的括号里,原因是:
	// 这里的left、right的增减是有一定的条件的,要在循环体中用if-else判断如何增减
    for(var left = 0,right = nums.length - 1;left <= right;) {
        if(Math.abs(nums[left]) < Math.abs(nums[right])) {
            arr[index--] = nums[right] * nums[right];
            right--;
        }else {
            arr[index--] = nums[left] * nums[left];
            left++;
        }
    }
    return arr;
};

209. 长度最小的子数组 

题目

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

示例:

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

思路

根据某一特定的条件来截取一定的子数组。

滑动窗口就是用两个指针来划定一定的区域,就数组来说,也就是可以用滑动窗口截取一段子数组。

所以,这道题应该是用滑动窗口来做

 窗口由start和end指针来框定

  • 如果整个窗口的值已经超过target,start就移动,缩小窗口;
  • 如果整个窗口的值没有超过target,end就移动,扩大窗口。

   每一次缩小窗口前,都记录这个窗口len有多大,如果窗口比原先的len小,就把len更新。

完整代码

核心代码:窗口缩小

窗口缩小要完成三件事:

1.窗口长度更新

2.窗口最前面的元素移除

3.窗口的start界限向前移动

 while(sum >= target) {
					// 1.窗口长度更新
            len = len < (end - start + 1) ? len : (end - start + 1);
					// 2.窗口最前面的元素移除
            sum -= nums[start];
					// 3.窗口的start界限向前移动
            start++;
            
        }

完整代码

var minSubArrayLen = function(target, nums) {
    var start = 0;
    var len = Number.MAX_SAFE_INTEGER;
    var sum = 0;
    for(var end = 0;end < nums.length;end++) {
        sum += nums[end];
        while(sum >= target) {
					// 1.窗口长度更新
            len = len < (end - start + 1) ? len : (end - start + 1);
					// 2.窗口最前面的元素移除
            sum -= nums[start];
					// 3.窗口的start界限向前移动
            start++;
            
        }
    }
    if(start == 0) {
        return 0;
    }
    return len;
};

细节

  1. 在js中,取大数的:是Number的一个类方法,用Number调,然后加上"最大安全数"的英文
var num = Number.MAX_SAFE_INTEGER;

59. 螺旋矩阵 II 

这道题关键的是怎么样把题目中 矩阵 这一图片,转换成用数组来进行描述的变成语言。

所谓模拟螺旋矩阵,其实是向数组里面放一些元素。

而且不能想着一下把这道题的代码写出来,要一点一点的修正才对。

思路

什么叫模拟螺旋矩阵

本题是对螺旋矩阵的模拟。

重点是怎么把这样一个模拟的过程,转换成编程语言。

所谓的“模拟螺旋矩阵”,其实是按照一定的规则,在向一个二维数组里面放数字。

如上图,其实就是把1放入res[0][0],把2放入res[0][1]...

区间不变性

在放入数字的过程中,需要很多轮来处理数字

这时候就要界定,每一轮处理哪些数字,也就是处理数字的区间是什么。

这里选择左闭右开的区间进行处理。

如上图,颜色一样的数字一起处理。

其实,区间不变形就是要保持每次的处理过程是一样的

如上图,每一行,或者每一列都处理前两个数字,最后一个数字留给下一次处理。

需要准备的量

存放结果的二维数组res

初始坐标

设定最开始从第一个格子走,此时startX=0,startY=0。

记录运动坐标

记录x的i,记录y的j

计数器count

res、startX=0,startY=0,i=0,j=0,count=1

对于四条边的模拟

首先看Carl哥第一个for循环代码,发现分为4部分:

也就说只要分别弄清楚4条边的这四个值怎么写,就能把整个过程模拟出来了。

坐标分析:每次循环,x、y坐标中总有一个是不变的,另一个作为for循环中的变量。

起始值:x、y坐标中变化的坐标的起始值

终止条件:在哪里停下

增减:是往前走还是往回走

对橙色边进行模拟

坐标分析:x=startX;y变化

res[startX][j] = count++;

起始值:y=startY

for(j = startY;;)

终止条件:y<3 - 1

for(j = startY;y < 3-1;) 

增减:箭头的方向是X正方向,向前的,所以j++

for(j = startY;y < 3-1;j++)

完整代码

for(j = startY;y < 3-1;j++) {
	res[startX][j] = count++;
}

黄色边进行模拟

坐标分析:y=j;x变化

起始值:x=startX

终止条件:x < 3 -1

增减:x往前走

for(i=startX;i < 3 - 1;i++) {
	res[i][j]=count++;
}

蓝色边进行模拟

坐标分析:x=i;y变化

起始值:Y=j

终止条件:y > 0

增减:y往回走

for(j=j;j > 0;j--) {
	res[i][j] = count++;
}

粉色边进行模拟

坐标分析:y=j;x变化

起始值:x=i

终止条件:x > 0

增减:x往回走

for(i = i;i > 0;i--) {
	res[i][j] = count++;
}

细节修饰

上述的代码,和完全正确的代码相差之处在于

  • 循环的终止条件
  • 循环次数
  • 奇数最后一格的填充

offset

offset是由于函数不断向内圈循环,于是内圈比起外圈,循环条件缩小

循环的次数

n = 3 循环1次

n = 4 循环2次

n = 5 循环2次

由归纳法,可知loop=n / 2;

看上图,又会发现一个问题,就是n是奇数的时候,中间会有一个空位

这时候其实只要

  • 判断n是否为奇数
    • n为偶数,不操作
    • n为奇数,把最后一个count填入

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值