代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

 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=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 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

思路:一开始也有想到按规律,想到每次按块分,后面的没有规律,放弃了,看了题解,发现就差一点,循环的规律还不是很清楚。

代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II_第1张图片

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=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. 螺旋矩阵

54. 螺旋矩阵

剑指 Offer 29. 顺时针打印矩阵

class Solution {
    public List spiralOrder(int[][] matrix) {
        //定义一个存储结果的变量。
        List 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= 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;

    }
}

补充:

ArrayListLinkedList各自常用的方法:

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 list = Arrays.asList(array);
当使用Arrays.asList()方法将数组转换为List时,返回的List是一个固定大小的列表。如果需要进行添加、删除等操作,可以使用ArrayList类来创建一个可变的List对象,并将转换后的列表传递给ArrayList的构造函数。例如:List mutableList = new ArrayList<>(Arrays.asList(array))。这样就可以对可变的列表进行操作了。

你可能感兴趣的:(算法刷题,算法)