LeetCode Day2

544 阅读3分钟

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例 1:

  • 输入:nums = [-4,-1,0,3,10]
  • 输出:[0,1,9,16,100]
  • 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]

示例 2:

  • 输入:nums = [-7,-3,2,3,11]
  • 输出:[4,9,9,49,121]

思路

和昨天我们做的第二题可以使用相同的双指针法,大致思路是两个指针一前一后在原数组两端,平方后更大的一个放进新数组中,放进去后指针往中间移动,直到两指针相遇。

题解

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int i=0,j=nums.size()-1,k=nums.size()-1;
        vector<int> r(nums.size(),0);
        while(i<=j){
            if(nums[i]*nums[i]>=nums[j]*nums[j]){
                r[k--]=nums[i]*nums[i];
                i++;
            }
            else{
                r[k--]=nums[j]*nums[j];
                j--;
            }
        }
        return r;
    }
};
  1. 初始化:
    • 使用三个指针:i、j 和 k。
      • i 指向数组的开始。
      • j 指向数组的结束。
      • k 指向结果数组的最后一个位置。
    • 初始化一个大小与 nums 相同的结果数组 r,所有元素都设置为0。
  2. 循环条件:i <= j
    • 这确保了数组中的每个元素都被考虑。
  3. 平方和比较:
    • 在每次循环中,比较 nums[i] 和 nums[j] 的平方。
    • 如果 nums[i] 的平方大于或等于 nums[j] 的平方:
      • 将 nums[i] 的平方放入结果数组的当前位置 r[k]。
      • i 指针向右移动一位。
    • 否则:
      • 将 nums[j] 的平方放入结果数组的当前位置 r[k]。
      • j 指针向左移动一位。
    • 在每次循环结束后,k 指针向左移动一位,以准备下一个位置。
  4. 返回结果:
    • 当所有元素都被考虑后,返回结果数组 r。

209.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。 示例:

  • 输入:s = 7, nums = [2,3,1,2,4,3]
  • 输出:2
  • 解释:子数组 [4,3] 是该条件下的长度最小的子数组。

提示:

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

思路

经典滑动窗口题,这种方法常用于解决数组/字符串的子序列问题,通过不断扩张和收缩子序列的长度从而做到寻找连续子序列

题解

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result=INT32_MAX;
        int i=0,sum=0,temp;
        for(int j=0;j<nums.size();j++){
            sum+=nums[j];
            if(sum>=target){
                while(sum>=target){
                    temp=j-i+1;
                    result=result<temp?result:temp;
                    sum-=nums[i++];
                }
            }
        }
        return result==INT32_MAX?0:result;
    }
};
  1. 初始化:
    • result 设置为 INT32_MAX,用于存储满足条件的最小子数组的长度。
    • i 指向子数组的开始位置。
    • sum 用于存储当前子数组的和。
    • temp 用于临时存储当前子数组的长度。
  2. 遍历数组:
    • 使用 j 作为循环变量,从0开始,每次增加1,直到数组的末尾。
    • 在每次循环中,将 nums[j] 加到 sum 中。
  3. 检查子数组的和:
    • 如果 sum 大于或等于 target,则进入内部循环。
    • 在内部循环中,计算当前子数组的长度 temp。
    • 更新 result 为 result 和 temp 中的较小值。
    • 从 sum 中减去 nums[i],并将 i 向右移动一位。
    • 当 sum 小于 target 时,退出内部循环。
  4. 返回结果:
    • 如果 result 仍然是 INT32_MAX,说明没有找到满足条件的子数组,返回0。
    • 否则,返回 result。

59.螺旋矩阵 II

给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 示例: 输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

思路

没什么特别的技巧,纯粹考察边界处理能力

题解

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n,vector(n,0));
        int start=0,loop=n/2,x=0,y=0;
        int count=1,offset=1;
        while(loop--){
            x=y=start;
            while(x<n-offset){
                result[start][x++]=count++;
            }
            while(y<n-offset){
                result[y++][x]=count++;
            }
            while(x>start){
                result[y][x--]=count++;
            }
            while(y>start){
                result[y--][x]=count++;
            }
            start++;
            offset++;
        }
        if(n%2){
            result[n/2][n/2]=count;
        }
        return result;
    }
};

  1. 初始化:
    • 创建一个 n x n 的矩阵 result,所有元素初始化为0。
    • start 表示每一圈的开始位置。
    • loop 表示需要进行的圈数,它是 n/2,因为每一圈都会填充两行两列。
    • x 和 y 用于遍历矩阵。
    • count 用于记录当前要填充的数字。
    • offset 用于计算每一圈的结束位置。
  2. 填充矩阵:
    • 对于每一圈:
      • 从左到右填充上边界。
      • 从上到下填充右边界。
      • 从右到左填充下边界。
      • 从下到上填充左边界。
    • 每完成一圈,start 和 offset 都增加1。
  3. 处理中心元素:
    • 如果 n 是奇数,那么矩阵的中心会有一个没有被填充的元素。将其填充为 count。
  4. 返回结果:返回填充好的矩阵 result。