一、209.长度最小的子数组
1. 看到题目的第一想法
使用快慢指针的方式,初始化都指向下标为0的数组元素;然后慢指针不动,挪动快指针,计算数组内元素总和,如果大于等于target快指针就停止挪动,并计算长度;然后依次挪动慢指针,重复上述循环;最后比较长度最小的子数组,返回它的长度。
2. 看完代码随想录的想法
使用双指针法,采用滑动窗口的思路
1)定义双指针,初始化双指针均指向索引为0的元素;定义一个数组用于计算滑动窗口内元素的总和,并且将它初始化为0;定义一个正无穷大的数,用于取得总和大于等于target的子数组最小长度;
2)使用while循环,为了防止指针溢出,当快指针小于等于len(nums)-1时进入循环,否则跳出循环;进入循环后,随着快指针依次向后移动一位,SUM数组依次计算快指针对应的元素总和;
3)嵌套子循环,即当sum总和大于等于target时进入循环来移动慢指针:首先要比较子数组最小程度和,即使用min函数取无穷大以及目前子数组长度(fast-slow+1)二者中的最小值;其次先计算移动慢指针后的数组和,即sum减去目前慢指针所指向的元素值,再移动慢指针向前一位;
4)完成最外层while循环后,需要将快指针向后移动一位
5)返回子数组的最小长度,如果不存在满足条件的子数组,则返回0
3. 实现过程遇到的困难及解决
1)想要定义数组,问题复杂化:只需要定义sum变量和min_len变量分别用于计算子数组长度和、取子数组的最小长度。min_len变量初始需要定义为无穷大,方便用于后续比较最小值:
2)没有想清楚应该遍历移动快指针还是慢指针:如果遍历移动慢指针,则和暴力解法没有区别,时间空间复杂度很高;因此只能遍历移动快指针,利用快指针先得到一个窗口,如何再移动慢指针逐渐缩小窗口。
3)关于先移动慢指针还是先缩小子数组的总和:如果先移动慢指针,则sum = sum - nums[slow]这一步的nums[slow]就会被减错;因此必须先减去目前慢指针对应的元素,再移动慢指针。
二、59.螺旋矩阵II
1. 看到题目的第一想法
首先,N的奇偶性需要分开讨论,N位奇数时其矩阵最后会多一个中心点;第二,需要使用循环函数按螺旋顺序来依次生成矩阵元素;第三,需要统一生成矩阵的函数形式,即左闭右开,每一次循环其最后一个元素留到下一个循环生成;并且最后一次循环需要注意N的奇偶性。但是问题在于,螺旋的旋转顺序和最后呈现的矩阵形式并不相同,不知如何处理。
2. 看完代码随想录的想法
1)螺旋矩阵本质上是一个二维数组,因此首先定义一个二维数组:
其次要根据给出的N去思考会旋转几圈,即 loop = n//2;然后需要定义起始点,因为每一条边的起始点都各不相同,即定义startx、starty;最后,由于每次旋转一整圈,下一圈的元素行列索引均会缩进一个单位,因此定义offset,并将其初始化为1;定义count变量用于为矩阵元素赋值。
2)要实现每一条边的遍历规则一致,因此采用左闭右开的方式进行遍历。第一条横向的边,i是不改变的,只有 j 依次递增;第二条纵向的边j到达最大值,保持不变,i 依次递增;第三条边的 j 到达最大值保持不变,i 依次递减,需要在range函数加上-1;最后一条边 j 处于最小值,而 i 处于最大值,i 依次向上递减;在每条边的遍历过程中,需要为矩阵元素使用count进行赋值,并且count依次+1;
3)进入下一个循环需要offset+1,startx+1, starty+1;
4)根据n的奇偶性,要知道当n是奇数时,则会比偶数多出一个中性点,mid = n//2, 最后加一个奇偶判断条件即可,中心点的值为nums[mid][mid]=count。
3. 实现过程中遇到的困难及解决
1)如何定义数组,数组下标从0开始,不能大于n:初始化数组nums = [[0] * n for _ in range(n)];
2)要将offset作为最外层的循环遍历,因为每完成一层外圈循环,偏移量就必须+1;
3)要保持遍历规则的统一,最后只需要判断n的奇偶性即可,奇数只需要直接为中心点进行赋值即可。