代码随想录训练营Day2:1.有序数组的平方 2.长度最小的子数组3,螺旋矩阵

本专栏内容为:代码随想录训练营学习专栏,用于记录训练营的学习经验分享与总结。

文档讲解:代码随想录

💓博主csdn个人主页:小小unicorn
⏩专栏分类:C++
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

Day2

  • 有序数组的平方
    • 题目分析
    • 思路:
      • 暴力:
      • 代码解决:
      • 双指针
      • 代码解决:
  • 长度最小的子数组
    • 题目分析:
    • 思路:
      • 暴力:
      • 滑动窗口法
      • 代码解决:
  • 螺旋矩阵
    • 题目分析:
    • 思路:
    • 代码解决:
  • 总结:

有序数组的平方

题目分析

题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
题目来源:977.有序数组的平方
在这里插入图片描述

思路:

暴力:

每个数平方之后,排个序。
在这里插入图片描述

代码解决:

class Solution 
{
public:
    vector<int> sortedSquares(vector<int>& nums) 
    {
         for(int i=0;i<nums.size();i++)
         {
             nums[i]*=nums[i];
         }
         //快速排序
         sort(nums.begin(),nums.end());
         return nums;
    }
};

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

双指针

本来数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么如何处理这个问题呢?
其实此时数组平方的最大值就在数组的两端,要么最左边,要么最右边,不可能是中间。

那么这时我们就可以考虑使用双指针法:
i指向起始位置
j指向终止位置。

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

如果nums[i] * nums[i] < nums[j] * nums[j]
那么result[k–] = nums[j] * nums[j]; 。

如果nums[i] * nums[i] >= nums[j] * nums[j]
那么result[k–] = nums[i] * nums[i]; 。

在这里插入图片描述
时间复杂度O(n)
空间复杂度O(n)

代码解决:

class Solution 
{
public:
    vector<int> sortedSquares(vector<int>& nums) 
    {
         int k=nums.size()-1;
         vector<int>result(nums.size(),0);
         
         for(int i=0,j=nums.size()-1;i<=j;)
         {
             if(nums[i]*nums[i]<nums[j]*nums[j])
             {
                 result[k--]=nums[j]*nums[j];
                 j--;
             }
             else
             {
                 result[k--]=nums[i]*nums[i];
                 i++;
             }
         }
         return result;
    }
};

长度最小的子数组

题目分析:

题目描述:给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
题目来源:209长度最小的子数组
在这里插入图片描述

思路:

暴力:

两个for循环,然后不断的寻找符合条件的子序列。

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) 
    {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.size(); i++) 
        { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.size(); j++) 
            { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

时间复杂度:O(n^2)
空间复杂度:O(1)

注意:用暴力法解决此问题,会超时。
在这里插入图片描述
在这里插入图片描述

滑动窗口法

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

那么滑动窗口如何用一个for循环来完成这个操作呢。
首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。
如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
此时难免再次陷入 暴力解法的怪圈。
所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。
那么问题来了, 滑动窗口的起始位置如何移动呢?

这里还是以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,来看一下查找的过程:
在这里插入图片描述

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

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

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
在这里插入图片描述

解题的关键在于 窗口的起始位置如何移动,如图所示:
在这里插入图片描述
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

代码解决:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) 
    {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        int i=0;
        for (int j = 0; j < nums.size(); j++) 
        {   
            sum+=nums[j];
            //注意这里使用while,每次更新i(起始位置),并不用比较子序列是否符合条件
            while (sum >= s)
            {
              // 取子序列的长度
              subLength = (j - i + 1); // 取子序列的长度
              result = result < subLength ? result : subLength;
              // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
              sum -= nums[i++]; 
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

螺旋矩阵

题目分析:

**题目描述:**给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
题目来源:59.螺旋矩阵
在这里插入图片描述
在这里插入图片描述

思路:

其实解决这个问题,就是思考,我们应该如何画出这个正方形呢?

这道题想解决掉的话,我们就要模拟一下画正方形的这个过程
模拟顺时针画矩阵的过程:

1.填充上行从左到右
2.填充右列从上到下
3.填充下行从右到左
4.填充左列从下到上
由外向内一圈一圈这么画下去。

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。

这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。

那么按照左闭右开的原则,来画一圈,看一下:
在这里插入图片描述

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。

这也是坚持了每条边左闭右开的原则。

代码如下,while循环里判断的情况是很多的,代码里处理的原则也是统一的左闭右开。

代码解决:

class Solution 
{
public:
    vector<vector<int>> generateMatrix(int n) 
    {
        // 使用vector定义一个二维数组
        vector<vector<int>> res(n, vector<int>(n, 0)); 
        // 定义每循环一个圈的起始位置
        int startx = 0, starty = 0; 
        // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int loop = n / 2; 
        // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int mid = n / 2; 
        // 用来给矩阵中每一个空格赋值
        int count = 1; 
        // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int offset = 1; 
        int i,j;
        while (loop --) 
        {
            i = startx;
            j = starty;

            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for (j = starty; j < n - offset; j++) 
            {
                res[startx][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for (i = startx; i < n - offset; i++) 
            {
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for (; j > starty; j--) 
            {
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for (; i > startx; i--) 
            {
                res[i][j] = count++;
            }
            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;
            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }
        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) 
        {
            res[mid][mid] = count;
        }
        return res;
    }
};

总结:

在这两天的数组学习中,我们收获还是不少的。
在Day1:
我们学习了二分查找,解决移除元素问题,我们头一次接触到了双指针算法,而在移除元素问题中,我们借助了双指针的思想,借助快慢指针,依次更新数组中的元素。

在Day2:

第一道题有数组的平方,对正常人来说,最简单的方法肯定就是暴力;
平方后加排序,在此基础上,我们对其进行改进,继续用到了我们的老朋友“双指针法”,因为数组是有序的,而最大值要么在起始位置,要么在终止位置,我们可以借助双指针,一个从前找,一个从后找。大的数就放在新数组里面,依次内推。

第二道题为长度最小的子数组,首先还是通过暴力,两层for循环遍历依次找出最小的子数组,但是呢,超时了。通过改进,我们学习了新的算法,滑动窗口算法。不难发现,滑动窗口的本质其实还是双指针算法,通过不断改变起始位置来调节窗口。所以,在每次遇到滑动窗口前。先想一下:窗口是什么,窗口的起始位置,终止位置又是什么?把这三个问题先处理好后,然后根据题目不断调节你的窗口,从而达到解题的效果。

第三道题为螺旋矩阵。这道题的难点就在于如何画出这个正方形,这就需要我们模拟实现,通过模拟实现,一步一步将这个正方形模拟出来,注意模拟过程中,具体要实现一个怎样的模拟,要么左闭右闭,要么左闭右开,模拟过程中严格遵循循环不变量规则。

到这里,数组的OJ题训练就到此为止了,希望通过两天的训练,对您能有收获。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/131821.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JRebel热部署——效率提升100倍(程序员工具必备)

1. 下载JRebel 2.激活程序 这里推荐一个免费获取jrebel激活服务器地址和激活邮箱的地址:点击进入 进入网站之后就可以获取到激活链接和邮箱 点击进入激活 复制过去激活就可以 然后就可以看到激活成功了 3.如何使用 代码修改后&#xff0c;直接CtrlShitF9 即可重新启动 4…

Cross-Origin跨站问题详解(跨站请求、跨站cookie)

背景&#xff1a;我部署frontend和backend到两个不同的docker容器&#xff0c;前端路径为http://localhost:3000&#xff0c;后端路径为http://localhost:4000。我设置了用户登录功能&#xff0c;并使用cookie进行session管理。当我的前端登录时&#xff0c;创建了一个session&…

bat脚本设置变量有空格踩到的坑

SET PATH c:\xxx;%PATH% 我想把一个路径作为path环境变量最前面的一个&#xff0c;所以使用了上面的语句。 但是没有生效&#xff0c;我还以为是其他什么原因&#xff0c;后来又有一个类似的需求&#xff1a; set output output\x64 结果在使用 %output% 的时候是一个空格&…

2024最新fl studio 21.2.0.3842中文版完整下载

FL Studio 21.2.0.3842中文版完整下载是最好的音乐开发和制作软件也称为水果音乐软件。它是最受欢迎的工作室&#xff0c;因为它包含了一个主要的听觉工作场所。2024最新fl studioFL Studio 21版有不同的功能&#xff0c;如它包含图形和音乐音序器&#xff0c;帮助您使完美的配…

Android---MVP 中 presenter 声明周期的管理

我们经常在 Android MVP 架构中的 Presenter 层做一些耗时操作&#xff0c;比如请求网络数据&#xff0c;然后根据请求后的结果刷新 View。但是&#xff0c;如果按返回结束 Activity&#xff0c;而 Presenter 依然在执行耗时操作。那么就有可能造成内存泄漏&#xff0c;严重时甚…

什么是记忆能力与泛化能力

更多NLP文章在这里&#xff1a; https://github.com/DA-southampton/NLP_ability 谈到WDL&#xff0c;一个经常看到的总结是&#xff1a;Wide and Deep 模型融合 wide 模型的记忆能力和 Deep 模型的泛化能力&#xff0c;进行两个模型的联合训练&#xff0c;从而兼顾推荐的准确…

IPV6网络技术详细介绍

无状态和有状态并不是相互对立的&#xff0c;他们可以同时存在&#xff0c;也就是一张网卡上可以同时出现通过RA生成的IP以及通过DHCPv6获得的IP。 从图中可以看到&#xff0c;顺序为&#xff1a; 1、Stateless自动配置“链路本地地址”2、Stateless自动配置“全球地址”&…

解决Scrapy爬虫多线程导致抓取错乱的问题

目录 一、概述 二、问题分析 三、解决方案 四、案例分析 五、总结 一、概述 Scrapy是一个流行的Python爬虫框架&#xff0c;可以轻松地抓取网页数据并对其进行解析。然而&#xff0c;在抓取过程中&#xff0c;如果使用多线程进行并发处理&#xff0c;可能会遇到数据抓取错…

基于SSM的学生就业管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【安卓13】谷歌原生桌面launcher3源码修改,修改桌面布局(首屏应用、小部件、导航栏、大屏设备任务栏)

前言 近期接到一个关于谷歌EDLA认证的需求&#xff0c;我负责的是谷歌原生桌面布局的修改&#xff0c;通过研究源码&#xff0c;将涉及到了一些修改思路发出来&#xff0c;大家可以参考一下有没有对你有用的信息。主要修改内容有&#xff1a; 1、搜索栏、底部导航栏未居中 2、…

RISC-V处理器设计(五)—— 在 RISC-V 处理器上运行 C 程序

目录 一、前言 二、从 C 程序到机器指令 三、实验 3.1 实验环境 3.11 Windows 平台下环境搭建 3.12 Ubuntu 平台下环境搭建 3.13 实验涉及到的代码或目录 3.2 各文件作用介绍 3.2.1 link.lds 3.2.2 start.S 3.2.3 lib 和 include 目录 3.2.4 common.mk 3.2.5 demo …

数据库安全:InfluxDB 未授权访问-Jwt验证不当 漏洞.

数据库安全&#xff1a;InfluxDB 未授权访问-Jwt验证不当 漏洞. InfluxDB 是一个开源分布式时序&#xff0c;时间和指标数据库。其数据库是使用 Jwt 作为鉴权方式&#xff0c;在用户开启认证时&#xff0c;如果在设置参数 shared-secret 的情况下&#xff0c;Jwt 认证密钥为空…

普华永道于进博会首发“企业数据资源会计处理一体化平台”

11月6日&#xff0c;在第六届中国国际进口博览会上&#xff0c;普华永道发布企业数据资源会计处理一体化平台&#xff08;英文名为Data Accounting Platform&#xff0c;简称DAP&#xff09;。该产品以普华永道“五步法”数据资源入表路径为理论依据&#xff0c;依托多年来普华…

QGIS导出Geoserver样式加载

1.在QGIS中加载并设计样式 加载数据之后按F7键即可打开样式编辑器 可以右键图层&#xff0c;点击属性中的符号化&#xff0c;有一个“基于规则”&#xff0c;可以设定规则或者比例尺范围。可以实现一定比例尺缩放可见或不可见的效果。 2.设计完样式之后右键图层导出 选择保…

【MATLAB源码-第75期】基于模拟退火算法(SA)的栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 模拟退火算法是一种启发式优化算法&#xff0c;通常用于解决组合优化问题&#xff0c;例如旅行商问题和图着色问题。它模拟了固体材料在退火过程中逐渐冷却达到稳定状态的行为&#xff0c;以寻找问题的全局最优解。 以下是模…

幸运素数(找出给定区间的所有幸运素数)

从键盘输入一个区间&#xff0c;程序判定输出区间的所有幸运素数。 (笔记模板由python脚本于2023年11月11日 12:44:43创建&#xff0c;本篇笔记适合熟悉python整型数据类型和基本编程技巧的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.o…

面试题:说一下公司常用MySQL分库分表方案

文章目录 一、数据库瓶颈1、IO瓶颈2、CPU瓶颈 二、分库分表1、水平分库2、水平分表3、垂直分库4、垂直分表 三、分库分表工具四、分库分表步骤五、分库分表问题1、非partition key的查询问题2、非partition key跨库跨表分页查询问题3、扩容问题 六、分库分表总结 一、数据库瓶颈…

前端技术搭建飞机大战小游戏(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分✨ 写在前面 上周我们实通过前端基础实现了弹珠游戏,当然很多伙伴再评论区提出了想法,后续我们会考虑实现的,今天还是继续按照我们原定的节奏来带领大家完成一个飞机大战游…

什么是特权会话管理

特权会话是由具有管理权限的用户在访问 IT 基础架构中的系统、设备或应用程序&#xff08;本地或远程&#xff09;时启动的 Internet 会话&#xff0c;包括在该会话期间执行的所有活动。 特权会话可以是数据库或安全管理员&#xff0c;通过 RDP 或 SSH 会话访问数据中心的机密…

欧拉角(横滚角、俯仰角、偏航角)、旋转矩阵、四元数的转换与解决万向节死锁

1、概述 物体的位姿&#xff08;位置和方向&#xff09;的描述方法一般使用两个坐标系来表示&#xff0c;一个是世界坐标系或地面坐标系&#xff0c;这里我都叫做地面坐标系吧&#xff0c;属于参考坐标系&#xff1b;另一个是自身的坐标系&#xff0c;以飞机为例来讲述一些常见…