977.有序数组的平方
思路:首先知道该数组为非递减数组,因此在平方后该数组是两边大,中间小的趋势。因此采用双指针解法
1.左右指针分别指向数组的第一个数和最后一个数,循环比较直至left > right。
2.每次比较将较大的数逆序更新至新数组,同时指向新数组的指针向前移动一位
3.最终返回一个平方后的非递减数组
注意:该题考虑到双指针解法即可解决。
java代码如下:时间复杂度O(n) 空间复杂度O(1)
public int[] sortedSquares(int[] nums) { //新数组 int[] newLength = new int[nums.length]; //左右指针 int left = 0; int right = nums.length - 1; //定义一个新变量负责新数组的更新 int index = right; while (left <= right) {//这里while的条件还存在问题 //这里left <= right的原因是保证遍历到每个元素,如果是<的话,会缺失一个元素 //逻辑:较大的数更新至数组 if (nums[right] * nums[right] > nums[left] * nums[left]) { newLength[index--] = nums[right] * nums[right]; right--; }else { newLength[index--] = nums[left] * nums[left]; left++; } } return newLength; }
209.长度最小的子数组
思路:
1.外层for循环遍历整个数组,定义为终止位置(若将外层for循环定义为初始位置,则可采用暴力解法,枚举所有子数组情况更新即可)。
2.记录当前遍历所有值的和,若大于目标值,移动初始位置。
3.移动初始位置前,记录当前子数组长度并更新。
注意:该题较为由双指针体现的滑动窗口思想。滑动窗口的终止位置的定义以及初始位置的移动非常关键!
代码如下:
public int minSubArrayLen(int target, int[] nums) {
//记录总和
int sum = 0;
//记录当前子数组长度
int subL = 0;
int result = Integer.MAX_VALUE;
//起始位置
int j = 0;
//控制终止位置
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
while (sum >= target) {
//此时总和大于目标值 记录当前长度
subL = i - j + 1;
//更新长度
result = Math.min(result, subL);
sum -= nums[j];
j++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
59.螺旋矩阵II
思路:
1.首先考虑的是循环圈数,应为n / 2。并且考虑到矩阵行列为奇数,填充中间的值
2.进入圈中,考虑每边的循环次数(坚持循环不变量原则),即每边的循环方式保持一致即可。
3.没圈结束,进入到下一个圈,此时起始位置改变,每边的循环次数也随之改变,保持每个大圈相同即可。
注意:该题主要考察对代码的掌握能力,同时保持每一圈的添加方式一致即可
代码如下:
public static int[][] generateMatrix(int n) {
//定义初始变量
int start = 0;
int loop = n / 2;
//定义矩阵的长宽
//控制每边添加数
int offset = 1;
//定义所添加的数和新数组
int count = 1;
int[][] arr = new int[n][n];
//控制转圈-循环次数
while (loop-- > 0) {
int i,j;
//第一条边
for (j = start; j < n - offset; j++) {
arr[start][j] = count++;
}
//第二条边
for (i = start; i < n - offset; i++) {
arr[i][j] = count++;
}
//第三条边
for (;j > start; j--) {
arr[i][j] = count++;
}
//第四条边
for (;i > start; i--) {
arr[i][j] = count++;
}
//首圈完毕
start++;
offset++;
}
//奇数单独赋值
if (n % 2 == 1){
arr[loop][loop] = count;
}
return arr;
}
总结:
这两天的学习完成了代码随想录的数组模块。所学知识如下:
二分查找
搜索数组中的某个数,使用双指针对整个区间进行二分,满足不同的条件是更新左边界或者右边界。最终找到该值。
注意:此时对二分区间的不同定义也会影响着更新区间的方式,只要整个循环过程中保持二分区间的一致定义即可轻松解决该题。
双指针
该题体现的是快慢指针思想,我们需弄清楚快慢指针的定义即可(快指针寻找非目标值,即需要更新的元素。慢指针定义为更新元素的索引)。
注意:通过快慢指针在1个for循环里完成两个for循环所完成的任务
滑动窗口
该题也是采用双指针做法,定义终止位置,在判断是否满足条件。从而确定起始位置的走向。
注意:该题主要考虑滑动窗口的起始和终止位置,以及滑动窗口的移动。
模拟法
该题并无太多算法,需要确定的是在遍历每个大圈是,遍历规则保持一致,及循环不变量原则。