题目链接:有序数组的平方
在昨天积极做扩展题目时,已经接触过本道题目,当时的方法是双指针法
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length - 1;
int[] arr = new int[nums.length];
int i = nums.length - 1;
while (left <= right){
if (nums[left] * nums[left] > nums[right] * nums[right]){
arr[i] = nums[left] * nums[left];
i--;
left++;
}
if (nums[left] * nums[left] <= nums[right] * nums[right]){
arr[i] = nums[right] * nums[right];
i--;
right--;
}
}
return arr;
}
}
本题求解较为顺利,思路也比较清晰。
出了一点小的错误:
对于如下示例:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
问题:我比较纠结在left和right比较过程中,-3和3的平方都是9,而数组中有两个9,是否需要在if语句大小比较中,加入两个等号。结果在只有一个元素的数组,如 [1] 报错。
解答:其实双指针在移动过程中,只会把符合条件的数加入数组,且另一个指针不动,如-3和3比较中,把3的平方9加入新数组,right指针移动,但-3的指针left不动,接下来是-3和2进行比较,同样能将-3的平方9加入数组中。
思维:不要太跳脱,在大脑中像虚拟机一样将代码一步步执行一遍试试看。
题目链接:长度最小的子数组
除了暴力求解,暂无思路。本题使用的滑动窗口思想很好理解,自己之前没太接触过。
滑动窗口法:不断调整子序列的终止位置和起始位置,从而得到我们想要的结果,本质还是双指针,时间复杂度为O(n)
本题的重点在于理解for循环代表的是起始指针还是终止指针。按照最常规思路,一般是起始指针,那么终止指针还是要遍历,时间复杂度与暴力求解时的两个for循环相同。
终止指针向后移动,直到sum+=nums[j] >=target,再去移动起始指针。看似也是两个循环,但起始指针循环的次数很少。判断i到j区间的最小子数组,i作为起始指针向后移动,sum=sum-nums[i],以此来寻找最小子数组。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int sum = 0;
int i = 0;
int result = Integer.MAX_VALUE;
int lenL;
for(int j = 0;j < nums.length;j++){
sum += nums[j];
while (sum >= target){
lenL = j - i + 1;
result = Math.min(result,lenL);
sum = sum - nums[i];
i++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
学会了滑动窗口的思路。除了常规思路,也要试着从另一个角度理解,比如在题目要去除值为val的元素,除了找到“==”的元素想办法去掉以外,可以选择“!=”的元素,忽略相等的元素;比如本题,移动起始指针比较麻烦,我们可以选择移动终止指针。
要慢慢学会跳脱常规思路,以及细心。
题目链接:螺旋矩阵II
晕,感觉过程会比较复杂,难以抽象出一个具体的代码。
循环不变量很重要,要有一个统一的处理方法才能接着进行循环,本题采用左闭右开的原则
一圈为一次循环,n*n矩阵循环n/2全,每循环一圈起点(startX,startY)都会发生变化,因此每一圈都要startX++,startY++,每循环一圈后圈也会变小,因此每一圈都要offset++
总结:startX和startY控制起点,offset控制循环圈的大小
奇数矩阵要特别注意
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0;
int start = 0;
int[][] res = new int[n][n];
int offset = 1;
int i,j;
int count = 1;
while (loop < n / 2){
for (j = start;j < n - offset;j++){
res[start][j] = count++;
}
for (i = start;i < n - offset;i++){
res[i][j] = count++;
}
for (;j > loop;j--){
res[i][j] = count++;
}
for (;i > loop;i--){
res[i][j] = count++;
}
loop++;
offset++;
start++;
}
if (n % 2 == 1) {
res[start][start] = count;
}
return res;
}
}
思路清晰的话很简单。总感觉过几天自己会忘掉,属于懂了这一题,但是还没学会分析方法。在大脑中模拟一遍循环过程,去寻找循环不变量。