今天这两题是数组中的Medium题,比起昨天的基础的数组增删改查操作的题目稍复杂。
LeetCode - 209. Minimum Size Subarray 最小长度子数组
解题目标:给定一个数组以及target,求出最短的并且总和大于等于target的子数组的长度。
想要获取一个最短的子数组的长度,也就是找出数组中某两个位置的index。本题主要采用了滑动窗口的思路,设置start和end两个指针表示头尾来截取目标子数组,end指针在前面探路,start指针根据当前总和是否超出target再决定是否向前移动,最终的结果也就是end - start + 1。本题的目标只是求最小长度,我们只要在循环中保持记录当前最小值就可以了,而不是打印出最终的子数组,因此不用过多思考最后start和end最后应该停留在什么位置。
滑动窗口其实和双指针的思想是类似的,我们使用双指针也就是为了能一次循环遍历之后直接找出答案,滑动窗口中的终止位置应该是跟着for循环正常走的,其精髓其实在于如何移动起始位置的逻辑。在我第一次写这题的时候犯了一个错误,中间更新start时判断写的是if,这样就会导致减去start的值有可能依然还是大于target,导致了一些情况没有被记录。在滑动窗口中因为不应该是一次性的判断,而是专注于在每一次循环中继续不断查找可能的解,因此这里需要用while循环持续地进行减start的操作直到小与target。
import static java.lang.Integer.MAX_VALUE;
import java.lang.Math;
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int start = 0;
int sum = 0;
Integer min_length = MAX_VALUE;
for (int end = 0; end < nums.length; end++) {
sum += nums[end];
while (sum >= target) {
min_length = Math.min(min_length, end - start + 1);
sum -= nums[start];
start++;
} // 持续移动start位置,更新滑动窗口大小
}
return min_length == MAX_VALUE ? 0 : min_length;
}
}
LeetCode - 59. Spiral Matrix II
解题目标:给定一个整数n,生成一个1~n^2的一个n*n正方形螺旋矩阵。
这题其实没有什么特别复杂的逻辑,重点在于如何在二维数组里转圈更新数字,以及特殊的边界条件处理。这里使用的边界处理是左闭右开的思路,一条边的最后一个元素留给下一条边来处理,每一次循环嵌套四个不同边的更新逻辑处理一圈。同时需要关注给定的矩阵需要转几圈(n / 2 圈),每个边的起始位置,以及当前所遍历的边长sideLen(n - currLayer - 1)。注意特殊情况,如果n为奇数,那么中心点的位置应该要单独更新。
class Solution {
public int[][] generateMatrix(int n) {
int num = 1;
int layer_num = n / 2;
int [][] res = new int[n][n];
for (int currLayer = 0; currLayer < layer_num; currLayer++) {
int sideLen = n - currLayer - 1; //当前需遍历的长度(边长-1)
//上
for (int a = currLayer; a < sideLen; a++) {
res[currLayer][a] = num;
num++;
}
//右
for (int b = currLayer; b < sideLen; b++) {
res[b][sideLen] = num;
num++;
}
//下
for (int c = sideLen; c > currLayer; c--) {
res[sideLen][c] = num;
num++;
}
//左
for (int d = sideLen; d > currLayer; d--) {
res[d][currLayer] = num;
num++;
}
}
//center
if (n % 2 != 0) {
res[n / 2][n / 2] = num;
}
return res;
}
}