算法|Day02

66 阅读2分钟

1. 977 有序数组的平方

image.png 题解: 采用双指针解法,由于数组中存在负数,因此平方之后数字的顺序可能会有变化,负数的平方还有可能大于负数,因此可以采用双指针从两头向中间遍历,然后采用结果数组,存储每次比较的值,代码如下

    public int[] sortedSquares(int[] nums) {
        // 双指针 指针从两头向中间遍历
        int i = 0;
        int j = nums.length - 1;
        int k = nums.length;
        int[] res = new int[k];
        while (i <= j) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                res[--k] = nums[i] * nums[i];
                i++;
            }else {
                res[--k] = nums[j] * nums[j];
                j--;
            }
        }
        return res;
    }
}

2. 209 长度最小的子数组

image.png 题解: 长度最小的子数组,那么肯定是这一整个数组n的一部分,因此可以采用滑动窗口法来求解,从i开始,到j结束,i和j之间的总和大于等于target就是一个子数组,记录下来,然后把i向前移动,继续滑动窗口,特别秒的算法,具体代码如下:

    public int minSubArrayLen(int target, int[] nums) {
        // 双指针 i表示滑动窗口起始位置 j表示滑动窗口终止位置
        int n = nums.length;
        int sum = 0;
        int res = Integer.MAX_VALUE; // 用来记录最后的长度;
        int i = 0;
        for (int j = 0; j < n; j++ ) {
            sum += nums[j];
            while (sum >= target) {
                int subL = j - i + 1;   //记录当时长度
                res = Math.min(res, subL);
                sum -= nums[i++];
            }
      
        }
        return res == Integer.MAX_VALUE ? 0: res;
    }
}

3. 59 螺旋矩阵II

image.png 题解: 非常经典的一个思路 左闭右开, 循环一圈 就相当于左闭右开区间 从左到右 从上到下 从右到左 从下到上的经历了左闭右开区间的一个循环,依次类推,代码实现如下:

    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        // 左闭右开的思路
        int loop = n >> 1; //表示循环的次数
        int offset = 1; // 控制每条边遍历的长度
        int startX = 0; // 每圈循环开始的位置
        int startY = 0; // 结束的位置
        int count = 1; //记录数
        int i,j;
        while (loop > 0) {
            i = startX;
            j = startY;
            // 从左到右 左闭右开
            for (j = startY; j < n + startY - offset; j++) {
                res[startX][j] = count++;
            }
            // 从上到下 左闭右开
            for(i = startX; i < n+startX -offset; i++) {
                res[i][j] = count++;
            }
            // 从右到左 左闭右开
            for(;j > startY; j--) {
                res[i][j] = count++;
            }
            // 从下到上 左闭右开
            for(;i > startX; i--) {
                res[i][j] = count++;
            }
            startX++; // 更新开始的位置
            startY++;

            offset += 2;
            loop--;
        }

        // 如果为奇数 需要单独给中间值进行赋值
        if (n % 2 ==1) {
            int mid = n >> 1;
            res[mid][mid] = n * n;
        }

        return res;
    }
}