977.有序数组的平方代码随想录
平方后形成凹函数,最大值要么在最左端出现要么在最右端出现,左右指针形成的窗口不断把较大值剔除出窗口,同时赋给新数组。
lass Solution {
public int[] sortedSquares(int[] nums) {
int l = 0 , r = nums.length - 1 , k = nums.length - 1;
int[] res = new int[nums.length];
while(l <= r){
if(nums[l]*nums[l] > nums[r]*nums[r]){
res[k] = nums[l]*nums[l];
k--;
l++;
}else{
res[k] = nums[r]*nums[r];
k--;
r--;
}
}
return res;
}
}
209.长度最小的子数组代码随想录
第一遍做思路有点混乱,sum收集完相应数组和后没有立即记录子数组长度,而是收缩了窗口,导致子数组长度计算出错
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0 , r = 0 , sum = 0 , res = Integer.MAX_VALUE;
while(r < nums.length){
sum = sum + nums[r];
while(sum >= target){
sum = sum - nums[l];
l++;
res = Math.min(res , r - l + 1);
}
r++;
}
return res;
}
}
数组和达不到target的情况没考虑
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0 , r = 0 , sum = 0 , res = Integer.MAX_VALUE;
while(r < nums.length){
sum = sum + nums[r];
while(sum >= target){
res = Math.min(res , r - l + 1);
sum = sum - nums[l];
l++;
}
r++;
}
return res;
}
}
最后一次订正:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0 , r = 0 , sum = 0 , res = Integer.MAX_VALUE;
while(r < nums.length){
sum = sum + nums[r];
while(sum >= target){
res = Math.min(res , r - l + 1);
sum = sum - nums[l];
l++;
}
r++;
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
滑动窗口相比暴力省去了一些不必要的比较,在两层循环暴力写法中, i 一个不落的遍历完每一个数组值,同时对于每个 i ,j 都要遍历一遍下标 i 以后的数组值。这种暴力也形成了 i 为左端,j 为右端的窗口,i 遍历完数组,j通过暴力遍历所有右边寻找 i 右边的最短子数组,做到不遗漏。
滑动窗口写法:
前提:非递减顺序 排序的整数数组 nums
窗口里子数组数值和sum >= target分两种情况:
1. 若sum > target,由于窗口左边值较小,左端尝试收缩,以探能否以更短的子数组数值和sum >= target ;
2.若sum恰 = target,窗口不会尝试收缩去寻找更短子数组因为此时本身就是最短的,left前进,right前进,相当于滑动。
这种做法相当于把每一个right左边的满足要求的最短子数组都能找出来,而right遍历完了整个数组,做到了不遗漏。
59.螺旋矩阵II代码随想录
class Solution {
public int[][] generateMatrix(int n) {
int i = 0 , j = 0 , loop = n / 2;
int startRow = 0 , startCol = 0 , count = 1 , offSet = 1;
int[][] matrix = int[n][n];//代码敲得少new数组都能错
while(loop--){//while条件得是一个能判断出0或1的表达式,不能是2、3/4之类
for(j = startCol; j < n - offSet; j++){
matrix[startRow][j] = count;
count++;
}
for(i = startRow; i < n - offSet; i++){
matrix[i][j] = count;
count++;
}
for(; j > startCol; j--){
matrix[i][j] = count;
count++;
}
for(; i > startRow; i--){
matrix[i][j] = count;
count++;
}
startRow++;
startCol++;
offSet++;
}
if(n % 2 == 1){
matrix[startRow][startCol] = count;
}
return matrix;
}
}
订正后代码
class Solution {
public int[][] generateMatrix(int n) {
int i = 0 , j = 0 , loop = n / 2;
int startRow = 0 , startCol = 0 , count = 1 , offSet = 1;
int[][] matrix = new int[n][n];
while(loop != 0){
for(j = startCol; j < n - offSet; j++){
matrix[startRow][j] = count;
count++;
}
for(i = startRow; i < n - offSet; i++){
matrix[i][j] = count;
count++;
}
for(; j > startCol; j--){
matrix[i][j] = count;
count++;
}
for(; i > startRow; i--){
matrix[i][j] = count;
count++;
}
startRow++;
startCol++;
offSet++;
loop--;
}
if(n % 2 == 1){
matrix[startRow][startCol] = count;
}
return matrix;
}
}
每一圈都要用四次循环分别填满4个边,每条边都涉及起始位置判断和终止位置判断。
每行或列的边界处理:留最后一个不填,遵循循环不变量原则。
每填完一圈startCol(填充行元素的起点)和startRow(填充列元素的起点)都要“手动”更新,起点都是闭区间,行尾n - offSet和列尾n - offSet也要“手动”更新,终点都是开区间。
每填完一圈剩余行数或列数-2,填多少圈就看n里有多少二,loop = n / 2 ,n奇数时中间单独空出一个,此时startRow = startCol ,最后单独填进去即可。
数组总结:
感觉都在遍历查找填充