您现在的位置是:首页 >技术交流 >LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II网站首页技术交流

LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II

码农小宇宙 2024-06-17 06:01:02
简介LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II

977. 有序数组的平方

 

暴力排序

        最直观的想法,莫过于:每个数平方之后,排个序,美滋滋,代码如下:

class Solution {
    public int[] sortedSquares(int[] nums) {
        for(int i = 0;i < nums.length;i ++){
            nums[i] = nums[i] * nums[i];
        }
        Arrays.sort(nums);

        return nums;
    }
}

双指针法

        数组其实是有序的, 只不过负数平方之后可能成为最大数了。

那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。

此时可以考虑双指针法了,i指向起始位置,j指向终止位置。

定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。

如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。

如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i]; 。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int l = 0;
        int r = nums.length - 1;
        int[] res = new int[nums.length];
        int j = nums.length - 1;
        while(l <= r){
            if(nums[l] * nums[l] > nums[r] * nums[r]){
                res[j--] = nums[l] * nums[l++];
            }else{
                res[j--] = nums[r] * nums[r--];
            }
        }
        return res;
    }
}

209. 长度最小的子数组

暴力解法

        两个for循环,然后不断的寻找符合条件的子序列,时间复杂度是O(n^2)。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int result = Integer.MAX_VALUE;
        int length = 0;
        int sum = 0;
        int k = 1;
        for(int i = 0;i < nums.length;i ++){
            sum = 0;
            for(int j = i;j < nums.length;j ++){
                sum += nums[j];
                if(sum >= target){
                    length = j - i + 1;
                    result = result < length ? result : length;
                    break;
                }
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
//代码最终超时了。。

滑动窗口

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于 窗口的起始位置如何移动,如图所示:

可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

class Solution {
    public int minSubArrayLen(int target, 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 >= target){
                result = Math.min(result,right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}

59. 螺旋矩阵 II

不涉及算法,模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

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

        while(loop++ < n/2){
            //上侧从左到右 左闭右开
            for(j = start;j < n - loop;j ++){
                res[start][j] = count ++;
            }

            //右侧从上到下 上闭下开
            for(i = start;i < n - loop;i ++){
                res[i][j] = count ++;
            }

            //下侧从右到左 右闭左开
            for(;j >= loop;j --){
                res[i][j] = count ++;
            }

            //左侧从下到上 下闭上开
            for(;i >= loop;i --){
                res[i][j] = count ++;
            }

            start ++;
        }

        if(n % 2 == 1){
            res[start][start] = count;
        }
        
        return res;
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。