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

97 阅读1分钟
  1. Squares of a Sorted Array Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.

 

Example 1:

Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Explanation: After squaring, the array becomes [16,1,0,9,100].
After sorting, it becomes [0,1,9,16,100].

Example 2:

Input: nums = [-7,-3,2,3,11]
Output: [4,9,9,49,121]

 

Constraints:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums is sorted in non-decreasing order.

带负数的升序数组内元素平方后,最大值存在于数组的两端。因此使用两个指针指向头部和尾部。 这题很难做in-place的操作,因为如果要保证空间复杂度O(1)的话就需要在每次移动数组元素的时候,将其余所有元素向前移动一位。所以还是使用额外一个数组较好。

定义一个数组ans[nums.length], 与原数组等长。 循环检查头尾指针,将较大的元素从ans[]的尾部从后往前放。就可以得到结果。 要注意头尾指针循环的结束判断应该为while(left <= right), 不然会漏掉一个元素。

代码:

class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] ans = new int[nums.length];
        int k = nums.length - 1;

        for(int i=0, j=nums.length - 1; i<=j;) {
            int l2 = nums[i] * nums[i];
            int r2 = nums[j] * nums[j];

            if(l2 < r2) {
                ans[k--] = r2;
                j--;
            }
            else if (l2 >= r2) {
                ans[k--] = l2;
                i++;
            }
        }

        return ans;

    }
}
  1. Minimum Size Subarray Sum Given an array of positive integers nums and a positive integer target, return the minimal length of a subarray whose sum is greater than or equal to target. If there is no such subarray, return 0 instead.

 

Example 1:

Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: The subarray [4,3] has the minimal length under the problem constraint.

Example 2:

Input: target = 4, nums = [1,4,4]
Output: 1

Example 3:

Input: target = 11, nums = [1,1,1,1,1,1,1,1]
Output: 0

 

Constraints:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104

这题使用滑动窗口,其实就是两个指针。 第一个指针为窗口起始index,为start, 另一个指针做循环数组, 为i。 [start, i] 为左右闭合区间,也就是这个滑动窗口。策略为:

  1. 若窗口内元素的SUM小于target, 挪动i,start不动。
  2. 若窗口内元素的SUM大于等于target, 挪动start,开始记录区间长度len,并在满足条件2的时候,更新len为更小值。这里需要循环挪动start,因为会存在{1,1,1,1,1,100...} target = 100 这样的情形。特别注意的是,挪动start时,SUM需减去start指向的元素。
  3. i移到数组末尾后,循环结束。 检查len值是否被更新过,因为len总是做最小值比较,初始化定义应为Integer.MAX_VALUE,最大整数值。如果len未被更新,返回0, 否则返回len

代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int len = Integer.MAX_VALUE;
        int sum = 0;
        int start = 0;

        for(int i=0; i<nums.length; i++) {
            sum += nums[i];

            while(sum >= target) {
                int current_len = i - start + 1;
                len = Math.min(current_len, len);
                sum -= nums[start++];
            }
        }

        return len == Integer.MAX_VALUE ? 0 : len;

    }
}
  1. Spiral Matrix II Given a positive integer n, generate an n x n matrix filled with elements from 1 to n2 in spiral order.

 

Example 1:

Input: n = 3
Output: [[1,2,3],[8,9,4],[7,6,5]]

Example 2:

Input: n = 1
Output: [[1]]

 

Constraints:

  • 1 <= n <= 20

这题似乎没什么取巧的方法,但思路清晰很重要。使用正确的策略可以保证思路清晰。 好的策略是,

  1. 以offset 来记录圈数,大循环每次写一圈数。
  2. 在每层大循环里,做四个小循环,写四条边。
  3. 在每个小循环中,只更新左闭右开的区间元素,留下最后一个元素给下一条边的任务,只在最后一条边,即处理左侧由下往上的边的时候,处理到最后。这样的好处是,每条边的逻辑处理是一致的。
  4. 注意,对n为奇数的情况,最中间的一个元素没有必要单独跑一圈,在大循环结束后,将最中间的元素直接赋值即可。

定义startx, starty为每一圈的起始坐标,每开始新的一圈前,startx++, starty++

代码为:

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] ans = new int[n][n];

        int startx = 0;
        int starty = 0;
        int offset = 1;
        int i,j;
        int count = 1;

        while(offset <= n/2) {
            for(j=starty; j<n-offset; j++) {
                ans[startx][j] = count++;
            }
            for(i=startx; i<n-offset; i++) {
                ans[i][j] = count++;
            }
            for(;j>offset-1;j--) {
                ans[i][j] = count++;
            }
            for(;i>offset-1; i--) {
                ans[i][j] = count++;
            }

            startx++;
            starty++;
            offset++;
        }
        //centre element when n is odd number
        if(n%2 == 1) {
            //odd
            ans[n/2][n/2] = n * n;
        }

        return ans;
    }
}