Day 2 第一章 数组part02
- 建议大家先独立做题,然后看视频讲解,然后看文章讲解,然后在重新做一遍题,把题目AC,最后整理成今日当天的博客
- 拓展题目可以先不做
- 今日任务
- 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,总结
977.有序数组的平方
1. 思路
🩸血的教训,自己想出一个思路后先别写代码,确定思路后先看看解析思路一样不一样,不一样的话可能会走很长的弯路
🩸一开始想的是先找到中间的最小值,太麻烦了,还是得转变一下思维
//思路正确后自己做版本
public int[] sortedSquares(int[] nums) {
int n[] = new int[nums.length];
int left = 0;
int right = nums.length-1;
int slow = nums.length-1;
while(left < right){
if(Math.abs(nums[left]) > Math.abs(nums[right])){
n[slow --] = nums[left] * nums[left]; //赋完值后slow++
left ++;
}else if(Math.abs(nums[left]) == Math.abs(nums[right])){
n[slow --] = nums[left] * nums[left];
n[slow --] = nums[left] * nums[left];
left ++;
right --;
}else if(Math.abs(nums[left]) < Math.abs(nums[right])){
n[slow --] = nums[right] * nums[right];
right --;
}
}
if(left == right){ //单独判断到中间左右相等的情况
n[slow] = nums[left] * nums[left];
}
return n;
}
2. 代码优化
while
循环中(left <= right)
有=
,不然会落下中间相等的数,还得单独判断if
判断不需要单独讨论Math.abs(nums[left]) == Math.abs(nums[right])
的情况,可以随便先记一个然后拿另一个和剩下的元素进行比较
如动画所示:
跟着这个动画走
//代码随想录里的标准代码
public int[] sortedSquares(int[] nums) {
int right = nums.length - 1;
int left = 0;
int[] result = new int[nums.length];
int index = result.length - 1;
while (left <= right) {
if (nums[left] * nums[left] > nums[right] * nums[right]) {
// 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
result[index--] = nums[left] * nums[left];
++left;
} else {
result[index--] = nums[right] * nums[right];
--right;
}
}
return result;
}
209.长度最小的子数组
- 题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。 拓展题目可以先不做。
- 题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
- 文章讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
- 视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
1. 自己的思路(超时)
public static int minSubArrayLen(int target, int[] nums) {
int size = 0;
int sum = 0;
for(int i = 0; i < nums.length; i ++){
int a = i;
sum = nums[a];
int l = 1;
while(sum < target && a < nums.length-1){
sum += nums[++ a];
l ++;
}
if(sum < target){
l = 0;
}else if(size == 0|| l < size) size = l;
}
return size;
}
2. 滑动窗口
双指针:一个表示滑动窗口的起始位置,一个表示滑动窗口的终止位置
- 先移动终止位置的指针找到一个
sum>target
的集合 - 再移动起始位置指针缩小这个集合
//思路对后自己写的代码
public static int minSubArrayLen(int target, int[] nums) {
int size = 0, temp = 0;
int sum = 0;
int start = 0, end = 0;
for(end = 0; end < nums.length; end ++){
sum += nums[end];
temp ++;
while(sum >= target){
if(sum - nums[start] < target) break;
else{
sum -= nums[start++];
temp--;
}
}
if(sum < target){
size = 0;
}else if(size == 0|| temp < size) size = temp;
}
return size;
}
3. 代码优化
- 不需要设置中间值,也不用每循环一次
result++
,直接通过right - left + 1
计算,通过Math.min()
函数取值。通过把result
设置成最大整数,只在有值时才给result
赋值 if-else
判断可以换成条件运算符result == Integer.MAX_VALUE ? 0 : result;
\\代码随想录代码
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
59.螺旋矩阵II
- 题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。
- 题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
- 文章讲解:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html
- 视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/
1. 自己的思路(通过)
代码
public static int[][] generateMatrix(int n) {
int a[][] = new int[n][n];
int b = 1;
int r1 = 0, r2 = n-1; //定义首行末行
int c1 = 0, c2 = n-1; //定义首列末列
while(b<=n*n){
for(int j = c1; j <= c2; j ++){//过程1:上行从做到右 n_n-2_n-4... a[r1][j] = b ++;
}
r1 ++;
for(int i = r1; i <= r2; i ++){//过程2:右列从上到下 n-1_n-3_n-5... a[i][c2] = b ++;
}
c2 --;
for(int j = c2; j >= c1; j --){//过程3:下行从右到左 n-1_n-3_n-5... a[r2][j] = b++;
}
r2 --;
for(int i = r2; i >= r1; i --){//过程4:左列从下到上 n-2_n-4... a[i][c1] = b++;
}
c1 ++;
}
return a;
}
2. 重点
循环不变量原则
代码随想录代码略
总结
- 题目建议:希望大家 也做一个自己 对数组专题的总结
- 文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E6%80%BB%E7%BB%93%E7%AF%87.html
其他知识点
Day 2
4. 直接用system.out.println();输出数组乱码
在IDEA中,对于一个数组,如int[] arr = new int[] { 2, 3, 67, 1, 34, 23 };
直接打印是结果是乱码System.out.println(arr);?如[I@b9e45a? 这是怎么回事
那是因为System.out.println
这个方法,默认调用的是对象的toString()
方法的内容
[I@b9e45a
中 [
表示数组,I
表示int类型,b9e45a
是对象名
这就是int[] arr
对象的toString
内容。
如果要打印数组,用Arrays这个工具类:
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.deepToString(arr)); //二维数组
5. Integer.MAX_VALUE;
Integer.MAX_VALUE表示int数据类型的最大取值数:2 147 483 647 Integer.MIN_VALUE表示int数据类型的最小取值数:-2 147 483 648
- Integer.MAX_VALUE+1=Integer.MIN_VALUE
因为: Integer.MAX_VALUE的二进制是0111 1111 1111 1111 1111 1111 1111 1111 Integer.MIN_VALUE的二进制是 1000 0000 0000 0000 0000 0000 0000 0000
0111 1111 1111 1111 1111 1111 1111 1111+1
=1000 0000 0000 0000 0000 0000 0000 0000