代码随想录算法训练营第二天 | LeetCode977 有序数组的平方、LeetCode 209 长度最小的子数组、LeetCode 59 螺旋数组Ⅱ
)
数组的特性是在内存中, 数组申请的内存必须是连续的,数组的元素无法实现真正意义上的删除,只能覆盖
LeetCode977 有序数组的平方
题目链接
使用方法: 双指针
思路:在数组所有元素平方之后, 数组中元素大小的走向为先下降后上升,也就是说可以把数组从中间值(第一个大于等于0的点)切开,可以看成两个已经排好序的新数组, 那对数组进行排序, 也就是对两个数组进行顺序。分别用两个指针指向两个数组的最大值进行比较,最大的放进新数组的末尾,然后再对指针进行操作, 继续循环, 直到跳出循环
public int[] sortedSquares(int[] nums) {
// 这是看了代码随想录对应的视频和文章写出的东西
// 新的数组数值大小走向为先下降后上身
// 说明数组的最大值只能诞生在数组的两端,而数组的最小值也只能在中间地带产生
// 我们可以创建一个相同容量大小的新数组,用两个新指针来分别指代数组的头尾,
// 比较两个指针指代的值的大小,谁大谁就将值赋值给新数组,并使对应的指针指向新址
// 判断条件为左指针必须小于等于右指针
// 不用担心赋值过程中新数组会产生越界的情况,因为他的容量和旧数组一致
int left = 0;
int right = nums.length-1;
int newStartIndex = right;
int[] res = new int[nums.length];
while(left <= right){
// 为什么没有判断相等的情况, 因为如果相等的话, 赋值那个指针都一样
// 这就是细节
if(nums[left] * nums[left] > nums[right] * nums[right]){
res[newStartIndex--] = nums[left] * nums[left];
left++;
}else{
res[newStartIndex--]= nums[right] * nums[right];
right--;
}
}
return res;
}
LeetCode 209 长度最小的子数组
题目链接
使用方法: 滑动窗口
个人感觉应该叫滑动窗帘, 毕竟现实生活中, 应该没有窗口是可以随意变化大小的吧(
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE; // 这个变量用来存储窗口的最小长度
int left = 0;
int sum = 0;
for(int right = 0; right < nums.length; right++){
sum += nums[right];
while(sum>= target){
result = Math.min(result, right - left + 1);
sum -= nums[left];
left++;
}
}
return result ==Integer.MAX_VALUE ? 0 : result;
}
LeetCode 59 螺旋数组Ⅱ
题目链接
这道题可以把顺时针分解为
从左到右,从上到下, 从右到左, 从下到上四个部分
四个部分对应着4个for循环
循环的圈数取决于输入的数据是不是奇数
loopNumber = n%2 == 1 ? n/2 +1 : n/2
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
// 题目的要求是元素要按按照顺时针排列,为了实现顺时针排列, 可以围着新建的二维数组按照顺时针的方向赋值, 每走完一圈,就调整下标,使得下标指向内圈的初始位置,继续循环
// 可以将顺时针拆解为4个方向,从左到右,从上到下, 从右到左, 从下到上
// 可以使用4个for循环分别完成对应赋值的操作
// 新问题来了, 4个for循环的循环区间应该多大,也就是for循环的终止条件是什么
// 我这里取得是左闭右开
// 那应该循环多少次才能完成这个程序呢
// 循环的次数也就是圈的次数,所以循环判断的条件应该是loop = 0 while(loop <3)
int element = 1;
int loop = 0;
int loopnumber = 0; // 循环圈数
loopnumber = n%2 == 1? n/2 +1 : n/2;
while(loop < loopnumber ){
// 从左到右
for(int i = loop; i <= n - loop - 1; i++){
res[loop][i] = element;
element++;
}
// 从上到下
for(int i = loop + 1; i <= n - loop - 1; i++){
res[i][n-loop-1] = element;
element++;
}
// 从右到左
for(int i = n-loop -2; i >=loop; i--){
res[n-loop -1][i] = element;
element++;
}
// 从下到上
for(int i = n - loop -2;i >loop; i--){
res[i][loop] = element;
element++;
}
// 外圈已经赋值完毕,更新圈数, 方便循环更新下一个圈
loop++;
}
return res;
}
今日总结:不要死磕,太难受了,应该每道题定个25分钟, 解不出来就看对应的视频和文章, 要不然太耗时了
对数组中的边界 和滑动窗口有了更深的理解
数组:
数组的特性尤为重要, 数组特有的连续, 特有的"删除"方式, 对应的算法感觉都是建立在数据结构是数组的基础上得出来的
数组中的边界感很有趣