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

1. 有序数组的平方

leetcode

视频讲解

第一个想法就是暴力写法,把所有的数平方再排序,太容易实现了,直接跳过

  • 时间复杂度:O(n + nlog n)

双指针法

昨天用过双指针法,今天自己写的时候就很有感觉,没费什么时间稍微Debug了下就搞定了。

左右各一个指针,对应的数平方后比大小,大的数就是rs[]的最后一位。

然后该指针移动,继续比较两个指针对应数的平方,大的数就是rs[]的倒数第二位。

以此类推……

class Solution {
    public int[] sortedSquares(int[] nums) {
        int size = nums.length;
        int[] rs = new int[size];
        int left = 0;
        int right = size - 1;
        int rs_right = size - 1;
        while(left <= right){
            if(nums[left] * nums[left] > nums[right] * nums[right]){
                rs[rs_right] = nums[left] * nums[left];
                left++;
            } 
            else{
                rs[rs_right] = nums[right] * nums[right];
                right--;
            }
            rs_right--;
        }
        return rs;
    }
}

2.长度最小的子数组

leetcode

视频讲解

一上来还是只想到了暴力解法,双指针考虑了一会,好像也不行,因为写着写着就成了暴力解法了

稍微看了下卡哥给的思路,看到了“滑动窗口”,好吧,没用过的新方法

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //暴力解法
        int size = nums.length;
        int lengthMin = size + 1;
        int sum = 0;
        for(int i = 0; i < size; i++){
            sum = 0;
            for(int j = i; j < size; j++){
                sum+=nums[j];
                if(sum >= target){
                    lengthMin = j-i+1 < lengthMin? j-i+1:lengthMin;
                    break;
                }
            }
        }
        return lengthMin <= size? lengthMin:0;
    }
}
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

看完了视频讲解的思路,自己写了下

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int size = nums.length;
        int lengthMin = size + 1;
        int sum = 0;
        int i = 0;
        for(int j = 0; j < size; j++){
            sum += nums[j];
            while(sum >= target){
                lengthMin = j-i+1 < lengthMin? j-i+1: lengthMin;
                sum -= nums[i++];
            }
        }
        return lengthMin <= size? lengthMin:0;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

一些录友会疑惑为什么时间复杂度是O(n)

不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。 

                                                                                                                              -- 代码随想录

其中 j 是终点,i 是根据情况移动的起点

j 从开始遍历数组,将它所遍历的数全部相加,当和大于等于target时,暂停向后遍历

此时减去 i 所指向的数,并判断sum是否仍然大于等于target,若大于则继续移动 i 并减去对应的数,否则用 j 从暂停的地方继续遍历

这个思路就像一个窗口一样,通过滑动一端,来使窗口内的数符合目标,再通过滑动另一端微调窗口,使得窗口内的数更优。就这样通过滑动窗口的两端,使得窗口遍历过所有符合target的集合,从而找出最优解。

 3.螺旋矩阵II

leetcode

视频讲解

看似很简单的一道题,绕了我半天跑出来还是一堆问题,最后看讲解,按照自己的理解写出来了。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] nums = new int[n][n];
        int count = 1;
        
        int loop = 0;
        int i,j; //[i][j]

         //[)
        while(loop < n/2){
            // → i不变,j变
            for(j = loop; j < n-1-loop; j++){
                nums[loop][j] = count++;
            }
            // ↓ j不变,i变
            for(i = loop; i < n-1-loop; i++){
                nums[i][j] = count++;
            }
            // ← i不变,j变
            for(; j > loop; j--){
                nums[i][j] = count++;
            }
            // ↑ j不变,i变
            for(; i > loop; i--){
                nums[i][j] = count++;
            }
            loop++;
        }
        if (n % 2 == 1) {
            nums[loop][loop] = count;
        }
        return nums;
    }
}
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

因为转一圈少两行两列,那么n行×n列的矩阵,只能循环 n/2 次,故 loop 从0开始要小于 n/2;

循环的总规则:[) 即不处理一行或一列得最后一个元素,交给变向后处理。

对于一个二维数组 [ i ][ j ] 对应的二维矩阵

[1,2,3]
[8,9,4]
[7,6,5]

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

横向移动:i 不变,j 变

纵向移动:j 不变,i 变

其中,循环次数越多,在每条边上需要移动的次数就越少,

每循环一次,它的出发点和终点都会随循环次数增加1,而随之减少1。

(具体的过程有点难用文字表达清楚)

最后当n为奇数时,中间会留一个数,需要再单独处理一下。

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