977.有序数组的平方
参考视频和详解
我的想法
暴力法,为什么时间复杂度是O(n + nlogn)???
优解思路
双指针法
- i 指向数组头,j 指向数组尾
- 创建一个和原数组长度一样的新数组result,让result指针n指向新数组的尾部
- 比较nums[i]*nums[i]和nums[j]*nums[j]的大小,大的值添加到新数组。大的值对应的指针进行移动
- nums[i]*nums[i] > nums[j]*nums[j]
- nums[n--] = nums[i]*nums[i]
- i++
- else:
nums[n--] = nums[j]*nums[j]
j--
Time Complexity
O(n)
代码实现
1. 定义双指针
int i = 0; (数组头)
int j = nums.length - 1 (数组尾)
2. 定义新数组
int[] result = new int[nums.length]
3. 定义新数组的指针
int n = result.length - 1 (数组尾)
4. while循环结束条件
while(i <= j)
5.循环体
比较nums[i]和nums[j]的平方,将大数添加到新数组尾,依次向前添加。
注意,添加完大数后,将原数组中对应的指针进行移动。最后,将新数组指针n往前移(n--)
while(i <= j){
if(nums[j] * nums[j] > nums[i] * nums[i]){
result[n--] = nums[j] * nums[j]; //给新数组添加元素
j--; //在原数组中移动大数对应的指针
}else{
result[n--] = nums[i] * nums[i];
i++;
6. 返回新数组
return result
遇到的问题
1. 应该如何移动指针?
谁的平方数大移动哪个指针
2. 循环结束条件?
当两个指针交锋,即left>right时,循环结束
3. 一些细节问题
往新数组result中放入元素时,应该放的是nums[i]或nums[j]的平方值,而不是nums[i]或nums[j]
4. java语法不熟悉
- 排序:Arrays.sort()没有返回值,返回类型是void
- 创建新数组:int[] array = new arrar[array.len]
209.长度最小的子数组
参考视频和详解
我的想法
暴力法,时间复杂度O(n2)
优解思路
滑动窗口
1. 窗口内是什么?
满足sum >= target的长度最小的连续子数组
2. i 和 j 到底谁指向窗口的终止位置?
j 指向滑动窗口的终止位置,起始位置动态移动
3. 如何移动起始位置?
j指针先找右边,找到右边再收缩左边,j 继续找更优解
代码实现
1. 定义双指针
int i = 0 (用来定义窗口的起点)
int j = 0 (在for循环处定义窗口的终点)
2. 定义最小值和初始化sum
int minVal = Integer.MAX_VALUE (用来保存最小长度)
int sum = 0
3. 循环条件:用窗口终点 j 遍历数组
for(int j = 0; j < nums.length; j++)
4. 取最小长度子数组
//j指针向右移,找到右边收缩左边(i向右移),j继续找更优解(j++)
for(int j = 0; j < nums.length; j++){
sum += nums[j];
while(sum >= target){
int len = j-i+1;
if(len < minVal){
minVal = len;
}
sum = sum - nums[i];
i++;
}
}
5. 返回值
判断有没有找到minVal,没找到返回0,找到返回minVal
遇到的问题
1. 如何比较并保存最小长度的值
int minVal = Integer.MAX_VALUE
If (len < minVal){
minVal = len
}
Integer.MAX_VALUE是java中Integer类的一个常量,代表了int类型能够表示的最大值
2. 没有考虑数组所有元素和都小于target的情况,比如target = 11, nums=[1, 1, 1, 1, 1,1]
应该考虑有没有找到minVal,没有找到返回0
return minVal == Integer.MAX_VALUE ? 0 : minVal;
59. 螺旋矩阵II
参考视频和详解
优解思路
坚持一个规则来处理每一条边(循环不变量)
左闭右开:最后一个节点留给下一条边来处理
代码实现
1. 循环起始位置定义
起始位置不断变化,所以不能在for循环里面定义
startX = 0;
startY = 0;
2. 临界点处理
定义一个临界值变量, n-offest表示不包含最后一个节点
offset = 1
3. 定义count,用来给值计数
count = 1
4. 定义 i, j 更新行列坐标
注意 i, j 要定义在循环体外
5. while循环结束条件:
while(n / 2)
n是边长,n/2是圈数。偶数被整除,奇数会留下中间一个点。
只需要在最后判断一下,如果n是奇数,nums[][]=val单独赋值
6. 循环模拟矩阵走向
- 遍历最上行 (0,0)(0,1)(0,2)
for(j = startY; j < n - offset; j++){
arr[startX][j] = count++;
}
- 遍历最右列 (0,2)(1,2)(2,2)
for(i = startX; i < n - offset; i++){
arr[i][j] = count++;
}
- 遍历最下行 (2,2)(2,1)(2,0)
for(;j > startY; j--){
arr[i][j] = count++;
}
- 遍历最左列 (2,2)(2,1)(2,0)
for(; i > startX; i--){
arr[i][j] = count++;
}
7. 更新定义值
每转一圈,startX++, startY++, offset++
8. 如果n为奇数, 需要对中间的值单独赋值
nums[startX][startY] = count
遇到的问题
1. 行列坐标如何更新,混淆了行列坐标
用i代表行,j代表列
2. startX, startY, offset的作用是什么?
- (startX, startY)更新每一轮矩阵循环的起始点
将这一轮循环的 I 初始化为startX, j 初始化为startY
- offset用来更新每条边的终点
3. 如果n为奇数,怎么处理?
把最后一个点赋值给arr[][],那么最后一个点怎么表示呢?
如图,奇数到了最后一个循环,只会剩余起始点(startX, startY)