Leetcoder Day2|有序数组的平方|长度最小的子数组 |螺旋矩阵II(数组部分结束)

语言:Java/C++

目录

977. 有序数组的平方

 解题思路:

暴力解法

双指针法

209.长度最小的子数组

 解题思路:

滑动窗口

59.螺旋矩阵II

 解题思路

今日心得


977. 有序数组的平方

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

  • 输入:nums = [-4,-1,0,3,10]
  • 输出:[0,1,9,16,100]
  • 输入:nums = [-7,-3,2,4]
  • 输出:[4,9,9,16,49]

 解题思路

暴力解法

这道题首先是有序的,但并没有强调无重复,因此结合昨天的内容,不能一上来就想用二分查找法。按照暴力解法全部元素平方然后用sort函数直接可以AC,不过时间复杂度较高,因为sort函数的本质是快排算法,时间复杂度为O(nlogn),再加上一次for循环,所以暴力解法的整体.

class Solution {
public:
    vector sortedSquares(vector& nums) {
         for(int i=0; i

时间复杂度:O(n + nlogn)

双指针法

首先我们先看一下示例,可以看到,平方过后的数组中最大的元素一定是在当前平方前元素的两边之一,不是最左就是最右。因此可以设置左右双指针,从两边向中间依次遍历和比较。并且题目中没有强调原地,因此可以建立一个新的数组,设置一个索引k指向新数组最后一个元素,每次遇到当前最大的元素便赋值给当前k所指向的位置,然后k在新数组前移,最后返回新数组即可。过程如下:

①定义新数组,设置索引

②双指针移动比较

③寻找到最大的那一个数据存在新数组中

还要注意的一点是因为要考虑到左右两边的元素,因此最好采用左闭右闭的情况。

class Solution {
public:
    vector sortedSquares(vector& nums) {
        vector result(nums.size(),0);//定义新数组
        int k=nums.size()-1; //设置索引
        for(int i=0, j=nums.size()-1;i<=j;){
            if(nums[i]*nums[i]

时间复杂度:O(n)


209.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

适用条件:与长度有关的,如一定长度内元素不重复或长度固定等,或窗元素和与某值有关,

 解题思路:

⚠️首先一定仔细审题,是 总和大于等于的而非只等于,今天在群里看到有录友直接审错题导致错误的。因为这个题不是简单的一个for循环就可以暴力解决的问题,因此直接排除了暴力解法的路子。
滑动窗口

滑动窗口就是不断的调节子序列的起始位置和终止位置,从而得到想要的结果。本质上也是一种双指针法,不过和双指针的一个区别是,在移动终止位置的时,起始位置是不可逆的,只能向后移动。

因为本题除了要关注元素和以外,还有一个重要的点:长度,我们需要找出满足条件的且长度最小的连续数组并返回其长度。因此设立起始和终止两个指针,初始时同时指向第一个元素,将终止指针不断后移形成一个子数组即窗口,并计算窗口的元素和,若当前元素和大于等于target,说明已经达到了临界条件,将这个长度记录下来,然后将起始指针后移直到不满足临界条件(这里用while循环),终止指针继续后移,看是否有其他满足临界条件且长度更小的窗口。

理清滑动窗口的思路主要有以下三点:

  • 窗口内是什么? 本题为满足其和 ≥ target的长度最小的连续子数组。
  • 如何移动窗口的起始位置?当前窗口的值大于s了,窗口就要向前移动了
  • 如何移动窗口的结束位置?窗口的结束位置不断向后移动即可
class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int result=INT32_MAX;
        int sum=0, sublength=0, i=0;  //设置和,窗口初始大小和起始指针
        for(int j=0;j=target){
                sublength=(j-i+1); //取窗口长度
                result=result
  • 时间复杂度:O(n)  每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
  • 空间复杂度:O(1)

59.螺旋矩阵II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

输入:n = 1
输出:[[1]]

Leetcoder Day2|有序数组的平方|长度最小的子数组 |螺旋矩阵II(数组部分结束)_第1张图片

 解题思路

每次一看到螺旋矩阵的问题,心里就会有点打怵,思路一直不是很清晰,因为数组在概念里一直是线性的,现在要变成一个非线形的情况,不是很有画面。还有一方面如卡哥所说边界条件的问题,写着写着就会蒙。要破解这个情况,需要谨记一点:坚持循环不变量原则,即一直坚持左闭右开或左开右闭的原则因此无论n是多少,这个题都变成了一个不断画四条边的问题。每次画完一圈,矩形的长度会减2,因此n/2为多少很关键。如果n为偶数,则循环n/2圈即可;如果n为奇数,则循环(n/2)+1圈,最后中间的位置为数组中最后一个数。过程如下:

  1. 初始化一个新的二维数组和起始位置,确定循环的圈数;
  2. 按照循环一致原则,从左到右,从上到下,从右到左,从下到上依次填充元素;
  3. 每循环完一圈,更新起始位置(均+1)并且控制边长(offset+1)
  4. 给n为奇数的中间位置赋值(最后一个元素)

Leetcoder Day2|有序数组的平方|长度最小的子数组 |螺旋矩阵II(数组部分结束)_第2张图片

class Solution {
public:
    vector> generateMatrix(int n) {
        vector> res(n, vector(n,0));//定义一个二维数组
        int startx=0;
        int starty=0, count=1, offset=1;//offset是控制边界的
        int loop=n/2;
        while(loop--){
            int i = startx;
            int j = starty;
            for(j;jstarty;j--){//从右往左的边
                res[i][j]=count++;
            }
            for(;i>startx;i--){//从下往上的边
                res[i][j]=count++;
            }
            //一圈结束后缩小所以起始位置要加1,边界也要在n的基础上缩小,offset加1
            startx++;
            starty++;
            offset++;
        }
        if (n%2){
            res[n/2][n/2]=count;
        }
        return res;

    }
};
  • 时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
  • 空间复杂度 O(1)

最后附上Leetcode上本题第一的题解,来自Krahets,结合过程思路更清晰且代码简洁:

Leetcoder Day2|有序数组的平方|长度最小的子数组 |螺旋矩阵II(数组部分结束)_第3张图片

class Solution {
    public int[][] generateMatrix(int n) {
        int l = 0, r = n - 1, t = 0, b = n - 1;
        int[][] mat = new int[n][n];
        int num = 1, tar = n * n;
        while(num <= tar){
            for(int i = l; i <= r; i++) mat[t][i] = num++; // left to right.
            t++;
            for(int i = t; i <= b; i++) mat[i][r] = num++; // top to bottom.
            r--;
            for(int i = r; i >= l; i--) mat[b][i] = num++; // right to left.
            b--;
            for(int i = b; i >= t; i--) mat[i][l] = num++; // bottom to top.
            l++;
        }
        return mat;
    }
}

今日心得

今天三道题之前很久之前也都接触过,因此前两道题问题不大,第三道题通过看视频加上画图梳理,再一次捋清和明确了以后遇到这种矩阵问题的思路,肯定还要多刷几遍加强熟练度的。加上写博客总用时一个半小时,继续努力。

你可能感兴趣的:(Leetcode算法刷题记录,算法,数据结构,leetcode,java,c++)