977.有序数组的平方
题目建议: 本题关键在于理解双指针思想
题目链接:力扣
文章讲解:代码随想录
视频讲解: 双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
思考:数组是固定的,不仅可以从小开始,还可以从大开始。
209.长度最小的子数组
题目建议: 本题关键在于理解滑动窗口,这个滑动窗口看文字讲解 还挺难理解的,建议大家先看视频讲解。 拓展题目可以先不做。
题目链接:力扣
文章讲解:代码随想录
视频讲解:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili
思路:没有思路,怎么想都太麻烦。参考代码随想录的文章,在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
连续子数组—— >滑动窗口
代码自己写:明白这个是符合条件的子数组遍历,然后取出最小的。
public int minSubArrayLen(int target, int[] nums) { int susum=0;//子总值 int sublen = 0;//子长度 int relen = nums.length; int sum=0; //双指针 for(int i=0,j=0;j<nums.length ;j++){ susum+=nums[j]; while(susum>=target){ sublen=j-i+1; relen = sublen < relen ? sublen:relen; sum=relen; susum -=nums[i++] ; } } return sum; } 时间复杂度:O(n) 空间复杂度:O(1)
拓展:哈希+滑动窗口
904. 水果成篮
题目链接:904. 水果成篮
思路:求最长子数组长度,直滑动窗口模板。本题中符合条件指窗口中水果种类是2。 用HashMap记录,Map<水果种类,出现频次>, 延伸右边界时,增加频次。缩进左边界时,减少频次。 频次为0时,从map删除。 map的大小为2时,正好符合条件。
最长窗口模板 for(枚举选择) 右边界 while(不符合条件) 左边界 更新结果
代码:
public int totalFruit(int[] fruits) { if (fruits == null || fruits.length == 0) return 0; int n = fruits.length; Map<Integer, Integer> cnt = new HashMap<>(); int ans = 0, left = 0; for (int i = 0; i < n; i++) { cnt.put(fruits[i], cnt.getOrDefault(fruits[i], 0) + 1); // 右边界 while (cnt.size() > 2) { cnt.put(fruits[left], cnt.get(fruits[left]) - 1); if (cnt.get(fruits[left]) == 0) { cnt.remove(fruits[left]); } ++left; } ans = Math.max(ans, i - left + 1); } return ans; } 时间复杂度:O(n) 空间复杂度:O(1)
59.螺旋矩阵II
题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。
题目链接:力扣
文章讲解:代码随想录
视频讲解:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili
思路:一开始也有想到按规律,想到每次按块分,后面的没有规律,放弃了,看了题解,发现就差一点,循环的规律还不是很清楚。
public int[][] generateMatrix(int n) { int[][] matrix = new int[n][n]; int loop = 0;//循环 int count = 1;//赋值 int start =0;//开始的点 int k,i; while(loop++ < n/2){ for(i =start;i<n-loop ; i++){ matrix[start][i] = count++; } for(k=start;k<n-loop ; k++){ matrix[k][i] = count++; } for(;i>=loop ; i--){ matrix[k][i] = count++; } for(;k>=loop ; k--){ matrix[k][i] = count++; } start++; } if (n % 2 == 1) { matrix[start][start] = count; } return matrix; } 时间复杂度 O(n^2): 模拟遍历二维矩阵的时间 空间复杂度 O(1)
拓展:
54. 螺旋矩阵
class Solution { public List<Integer> spiralOrder(int[][] matrix) { //定义一个存储结果的变量。 List<Integer> list = new ArrayList<>(); //为空时,直接退出。 if(matrix ==null || matrix.length ==0){ return list; } //构造一个 m*n 的一个矩阵 int m = matrix.length; //行 int n = matrix[0].length; //列 int i =0; //层数(从外向内的层数) int count = (Math.min(m,n)+1)/2; //统计从外向内的总层数,至少为一层 while(i<count){ //从左往右 //行不变,列逐渐增大,特被这里 n-i是为了控制他在从外到内,第几层。最外面为第0层 // j 为变化的列 for(int j = i;j<n-i;j++){ list.add(matrix[i][j]); } //从上往下 //行逐渐增大,列不变 // j 为变化的行 // (n-1)-i 为最右边一列 for(int j = i+1;j<m-i;j++){ list.add(matrix[j][(n-1)-i]); } //从右往左 //行不变,列逐渐减小 // j 为变化的列 // (n-1)-(i+1) 这里的 i + 1是为了去除最右下角那个数, // n-1-i 指向最右边的列, j >= i 是为了保证当行为最后一行 //这里的 (n-1-i) != i 这是用来保证,是属于同一层的 for(int j= (n-1)-(i+1); j>= i && (m-1-i != i); j--){ list.add(matrix[(m-1)-i][j]); } //从下往上 //列不变,行逐渐减小 // j 为可变的行 //(m-1)-(i+1) 是为了去除最左上角的数 // j >= i+1,是为了保证当前行为第二行 // (n-1-i) !=i 这是用来保证,是属于同一层的。 for(int j = (m-1)-(i+1);j >= i+1 && (n-1-i) !=i; j--){ list.add(matrix[j][i]); } i++; //层数加一,继续向内层递进 } //返回结果 return list; } }
补充:
ArrayList
和LinkedList
各自常用的方法:
ArrayList
的常用方法:
add(element)
: 将元素添加到列表的末尾。add(index, element)
: 将元素插入到指定索引位置。get(index)
: 获取指定索引位置的元素。set(index, element)
: 替换指定索引位置的元素。remove(index)
: 移除指定索引位置的元素。size()
: 返回列表的大小,即元素的数量。isEmpty()
: 判断列表是否为空。contains(element)
: 判断列表是否包含指定元素。indexOf(element)
: 返回指定元素在列表中首次出现的索引位置。clear()
: 清空列表中的所有元素。
LinkedList
的常用方法:
add(element)
: 将元素添加到列表的末尾。addFirst(element)
: 将元素添加到列表的开头。addLast(element)
: 将元素添加到列表的末尾。getFirst()
: 返回列表的第一个元素。getLast()
: 返回列表的最后一个元素。removeFirst()
: 移除并返回列表的第一个元素。removeLast()
: 移除并返回列表的最后一个元素。size()
: 返回列表的大小,即元素的数量。isEmpty()
: 判断列表是否为空。contains(element)
: 判断列表是否包含指定元素。indexOf(element)
: 返回指定元素在列表中首次出现的索引位置。clear()
: 清空列表中的所有元素。int numberOfRows = array.length; // 获取行数 int numberOfColumns = array[0].length; // 获取列数
List转换为数组:
String[] array = list.toArray(new String[list.size()]);
数组转换为List:
List<String> list = Arrays.asList(array); 当使用Arrays.asList()方法将数组转换为List时,返回的List是一个固定大小的列表。如果需要进行添加、删除等操作,可以使用ArrayList类来创建一个可变的List对象,并将转换后的列表传递给ArrayList的构造函数。例如:List<String> mutableList = new ArrayList<>(Arrays.asList(array))。这样就可以对可变的列表进行操作了。