首页 > 其他分享 >代码随想录第2天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,数组总结

代码随想录第2天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,数组总结

时间:2024-06-06 22:34:39浏览次数:13  
标签:977 vector int 复杂度 随想录 循环 数组 指针

题目:977.有序数组的平方

思路:

first. for循环,平方 ,然后sort排序, 提交通过 啊哈~|但时间复杂度大 O(n + nlogn), ->O(nlogn)的时间复杂度,题目进阶要求时间复杂度为 O(n)
second. 双指针。题目为有序数组,包含负数,则平方后,最大值在数组的两头,则使用双指针进行,
两个比较大小,大的存入新数组,进行从大到小、从后往前存入新数组。
时间复杂度为O(n)

坑:

题目是 有序 数组 且可以使用 额外的 内存空间,和之前做过的题目区分开啊

补充:

排序函数sort(begin,end,cmp):

  1. 根据数量级不同,自动选择合适的排序方法(快排,堆排等)
  2. cmp可省略,默认是从小到大排序,从大到小则将cmp换成 greater<类型>()
  3. begin 为指向数组第一个元素的指针,end 为指向数组 尾后 的指针 (最后一个元素的下一个位置)
  4. 头文件要包含 #include<algorithm>
  5. 可以根据需求进行自定义排序cmp

题目:209.长度最小的子数组

思路:

随想录的提示
1.暴力法
两层for循环(i,j),每次循环从第i个元素开始,往后,循环依次累加,寻找符合条件的子数组,第二层循环的起始条件是j=i
一个for循环表示数组的起始位置,一个for表示数组的终止位置。
时间复杂度:O(n^2)
空间复杂度:O(1)
2.采用滑动窗口
滑动窗口,也是双指针的思路 ,主要明确,两个指针指向的含义是什么
本题,暴力法是两层for循环,一个for循环表示数组的起始位置,一个for表示数组的终止位置。
那么采用双指针i,j,且时间复杂度要求为O(n)的情况下,表示循环遍历的j指针,指向终止位置
两个指针之间的数组就是最求的子数组s,随着j的后移,s的值总和满足大于target则记下子数组个数len,
之后i后移,看缩减后的子数组s是否还>target,大于则更新len值

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

时间复杂度:O(n) 解释:时间复杂度,基本操作的执行次数,每个元素被执行两次,所以是 2 × n 也就是O(n)
空间复杂度:O(1)

坑:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
       //滑动窗口
        int sum=0; //记录子数组总和
        int len=0;// 记录子数组长度
        int m=nums.size()+1;  //记录子数组最小长度  错误 ,初始值应设定为一个较大的值,m=INT32_MAX
        int i=0;
        for(int j=0;j<nums.size();j++){
             sum+=nums[j];
            while(sum>=target){  //错误 不是if 是while ,持续判断,滑动窗口
                len=j-i+1;       //错误每次都更新len,没设置保存最小长度的变量
                m=len<m?len:m;
                sum-=nums[i];  //这两步可以简化为一步  i++的特性,sum-=nums[i++]
                i++;
            }
        }
        return m==nums.size()+1?0:m;  //判断m的值是否改变,错误 忽略 没有符合条件的情况,返回值为0
    }
};

补充:

问号运算符 <表达式1>?<表达式2>:<表达式3> fg: result=a>b? a:b;

题目:59.螺旋矩阵Ⅱ

思路:

视频解析
显然是个循环, 循环就要坚持 循环不变量
循环不变量是 每条边的处理规则 ,z转一圈为一次循环,然后这个循环次数是 n/2
想不出来,B站视频大概懂了,但是代码有些困难,看的力扣上Krahets大神的题解矩阵解释图
每次循环的起始位置和终止位置都不是固定的,所以设为变量
理解转一圈是一次循环, 那么 一次循环里面 需要经历 从左到右,从上到下,从右到左,从下到上 四个小遍历
本题关键在于 矩阵四个角怎么分析,矩阵的四个角直接按顺序包含进去,从左到右结束,上边界减一,再从上到下
(从左到右 ,l到r是0到n-1, 从上到下 ,t到b是1到n-1;因为[1,n-1],在上一个小遍历的时候已经被填充了,)

坑:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> matrix(n,vector<int>(n));
        int num=1 ; //需要填充进去的数值, 共填充n*n个数 
        int t=0,b=n-1,l=0,r=n-1;  
        //四个小遍历的i,j的初始值和终止是变化的,所以设定为变量
        // 从横轴看,从左到右 ,l到r是0到n-1,
        // 从纵轴看,从上到下 ,t到b是0到n-1;
        while(num<=n*n){
            //从左往右
            for(int j=l;j<=r;j++){ 
                matrix[t][j]=num++;  //注意的分清不变量和变量
            }  
            t++;  // 上边界减少,
            //从上到下
            for(int i=t;i<=b;i++){
                matrix[i][r]=num++;
            }
            r--;
            //从右往左
            for(int j=r;j>=l;j--){
                matrix[b][j]=num++;
            }
            b--;
            //从下到上
            for(int i=b;i>=t;i--){
                matrix[i][l]=num++;
            }
            l++;
        }
        return matrix;
    }
};

补充:

vector声明二维数组
vector<vector<int>> table(size1, vector<int>(size2, 0)); // size1 是外围容器大小, size2是内部容器大小,0是赋的初值。 //即 容器(大小,内容)
for循环
for(单次表达式;条件表达式;循环体)每部分只能写一个表达式

数组总结

数组是存放在连续内存空间上的相同类型数据的集合

数组元素不能删除,只能覆盖,整体移动元素
数组和双指针真是相配,
学习了二分法,快慢双指针,滑动窗口,螺旋啊。
明确题目所给区间的开闭情况,循环的起始位置,终止位置及相应条件。

今日总结

螺旋矩阵题解看懂了,自己想出来很困难
力扣提交记录有备注啊!!!!页面小,之前没看见,好啊!!有备注!!太好了!!!

标签:977,vector,int,复杂度,随想录,循环,数组,指针
From: https://www.cnblogs.com/bamboo2233/p/18236206

相关文章

  • 代码随想录算法训练营第二十九天 | 491.非递减子序列
    491.非递减子序列题目链接文章讲解视频讲解层间去重:回溯法相当于深搜,所以所以是一直递归到叶节点才开始回溯;每次进入backtracking也就进入了搜索树的下一层,所以每进入一层需要用一个used_set来记录使用过的元素;classSolution{private:vector<int>sub;vecto......
  • 字符数组VS字符串(一文搞懂有什么区别)
    当你在C++的程序中,经常会遇到两种字符串的表达方法,一种是以字符数组的方式,还有用string的,这二者到底有什么不同?下文将会帮彻底弄懂。因为许多函数参数当需要传入字符串的时候,有的代码中使用指向字符数组的指针来传递字符串,其实C++中传入字符数组,就相当于传入一个指向该数......
  • 数组array 和 &array的区别
    问题对于数组array和&array有什么区别呢?先说答案array:指向数组第一个数地址的指针&array:指向整个数组地址的指针所以直接打印的话,地址是一样的.但是如果+1的话,那么array是增加sizeof(int)大小,&array是增加sizeof(int)*array.size()测试#include<iost......
  • 记录工作中常用的 JS 数组相关操作
    工作中难免会遇到各种各样的数据结构,较为全面的了解数组操作,对于复杂数据结构的处理会非常有用且节省时间所以想在这里总结一下工作中常用的数组操作,都是一些非常基础的知识,大家看个乐就好~目录工作中常用的数组方法常见数组方法中的用法、以及坑slice()和splice()方法......
  • 代码随想录算法训练营第一天 | 704. 二分查找 27. 移除元素
    704.二分查找题目:给定一个n个元素有序的(升序)整型数组和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。提示:1.你可以假设nums中的所有元素是不重复的。2.n将在[1,10000]之间。3.nums的每个元素都将在[-9999,9999]之间。解题:思路:二......
  • §2. 隐函数组
    掌握隐函数组的概念和隐函数组定理,会求隐函数组的偏导数。掌握反函数组定理,会求反函数组的偏导数。难点:求解隐函数组的偏导数(公式法或直接求偏导数然后解方程组)。重点习题:例1、例2、例3   卡尔·雅可比(CarlGustavJacobJacobi,1804~1851),德国数学家。1804年12月10日生......
  • 代码随想录算法训练营第二十八天 | 93.复原IP地址
    93.复原IP地址题目链接文章讲解视频讲解classSolution{private:vector<string>ip;vector<string>result;public:vector<string>restoreIpAddresses(strings){backtracking(s,0);returnresult;}voidbacktrackin......
  • 输出有10个元素的整型数组各元素的值
    (1)下标法编写程序:(2)指针法:将上面程序第7行和第10行的a[i]改为"*(a+i)"。(3)用指针变量指向数组元素编写程序:运行结果:对3种方法的比较:        方法(1)和(2)的执行效率是相同的。C++编译系统是将a[i]转换为*(a+1)处理的,对每个a[i]都分别计算地址a+ixd,然后访问该元素。第......
  • 数据转换-位串字节数组
    utils.c#include"utils.h"intBitstr2ByteArr(unsignedchar*bs,unsignedchar*ba,int*lba){inti,j;for(i=0,j=0;j<*lba;j++){ba[j]=0;for(intk=0;k<8;k++){if(bs[i]=='......
  • js 数组各种常见的操作
    JavaScript中的数组提供了多种操作方法,以下是一些常见的数组操作示例:1创建数组javascriptconstnumbers=[1,2,3,4,5];2访问数组元素javascriptconsole.log(numbers[0]);//输出:13修改数组元素javascriptnumbers[0]=10;4数组长度javascriptc......