【算法练习Day2】有序数组的平方长度最小子数组螺旋矩阵II

news2024/11/28 0:53:03

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 有序数组的平方
    • 暴力求解
    • 双指针法
  • 长度最小子数组
    • 暴力求解
    • 滑动窗口
    • 其他问题
  • 螺旋矩阵II
  • 总结:

有序数组的平方

有序数组的平方

暴力求解

这一题的暴力解法思路就是先将每一个数按顺序平方,存储到一个数组中,处理完全部后再进行排序。时间复杂度应该是O(n*logn)。n是处理每个数的平方的过程,logn是快排的时间。

代码如下

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

双指针法

是对于双指针的一种巧妙运用,具体思路为:由于数组传入时已经有序,所以在正负数同时出现时,大数应该都为两边分布,而小数则集中在中间(若两数相等则随意取一个放入),分别设立两个指针指向数组第一个元素和最后一个元素,比较二者平方值,将较大值插入数组,且将对应指针向前或向后移动,直到两个指针遍历完真个数组。

代码如下

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> ret(nums.size(),0);//要告诉系统开多大空间
        int left=0;
        int right=nums.size()-1;
        int k=nums.size()-1;
        while(left<=right)
        {
            if((nums[left]*nums[left])<(nums[right]*nums[right]))
            {
                ret[k--]=(nums[right]*nums[right]);
                right--;
            }
            else
            {
                ret[k--]=(nums[left]*nums[left]);
                left++;
            }
        }
        return ret;
    }
};

易错:注意最后一个元素为nums.size()-1,不然越界访问

长度最小子数组

长度最小子数组

这道题对于很多新手来说,都很头疼,一开始做的时候没有思路

暴力求解

这道题暴力破解对于此题是通不过的,数据过多,会显示超过时间。

class Solution {
public:
    int minSubArrayLen(int target, 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 >= target) { // 一旦发现子序列和超过了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循环完成原本两层循环进行的操作。循环中变量 j 控制的是滑动窗口的结束位置,而起始位置,会由于数据的判断成功而动态的发生改变。一开始两个都指向第一个位置,j向后移动找到目标值target后,起始指针 i 向后移动,寻找在数组元素>=target的同时,长度最小的子数组。

要点:要明确循环中 j 指向哪个位置,起始位置还是终点位置,其二要知道起始位置什么条件会动态变化

代码如下

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

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

时间复杂度 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

一开始知道这个思路,感觉并没有和双for暴力解决有什么太大的区别,后来发现确实很巧妙,子数组的和被判>=target后,起始位置不断缩小能够帮助我们找到最小长度的子数组,而当缩小后,子数组和小于target时,终点位置还能够向后遍历,实现了动态的窗口滑动,这也是为什么起始位置滑动代码块用while循环,而不是用if来只走一次移动的原因所在。

其他问题

● 加入滑动窗口中有负数怎么办?
如果有负数的话感觉也不能用滑动窗口了,因为有负数的话无论你收缩还是扩张窗口,你里面的值的总和都可能增加或减少,就不像之前收缩一定变小,扩张一定变大,一切就变得不可控了。如果要 cover 所有的情况,那每次 left 都要缩到 right,那就退化为暴力了。

● 双指针和滑动窗口有什么区别,感觉双指针也是不断缩小的窗口。这道题,用两头取值的双指针,结果错了?
因为两头指针走完相当于最多只把整个数组遍历一遍,会漏掉很多情况。滑动窗口实际上是双层遍历的优化版本,而双指针其实只有一层遍历,只不过是从头尾开始遍历的。

螺旋矩阵II

59. 螺旋矩阵 II - 力扣(LeetCode)

刚开始看到时候很懵,不知道如何下手,没有思路,这道题实际上就是模拟矩阵,创建一个二维数组,用循环来走矩阵的边,通过下标的调整来进入内层循环,实现螺旋矩阵的操作。

代码如下

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

        while(loop--)
        {
            j=starty;
            i=startx;

			// 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for(j=starty;j<n-offset;j++)
            {
                ret[startx][j]=count++;
            }
			 // 模拟填充右列从上到下(左闭右开)
            for(i=startx;i<n-offset;i++)
            {
                ret[i][j]=count++;
            }
			// 模拟填充下行从右到左(左闭右开)
            for(;j>starty;j--)
            {
                ret[i][j]=count++;
            }
			 // 模拟填充左列从下到上(左闭右开)
            for(;i>startx;i--)
            {
                ret[i][j]=count++;
            }
            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;
			// offset 控制每一圈里每一条边遍历的长度
            offset++;

        }
        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if(n%2)
        {
            ret[mid][mid]=n*n;
        
        return ret;

    }
};

注意:第一是要明确,模拟遍历的各条边代码实现时,应该有规律,而不能一条边一个规律,这样很容易写崩,上述代码就是采用左闭右开的规律,即每条边遍历第一个元素到倒数第二个为止,这样跳出循环后,变量指向的就是下一条边的起点,很方便。

第二是要注意循环判断条件,也就是除了要写n减去最后一个不能取的数字以外,还要加上起始位置的下标(第一圈模拟可能看不出作用,但是对后面内圈模拟作用很大)加上起始下标才能不出错。

第三是offset的改变,每进入一圈,各边减少两个数字的遍历,以第一条边为例,第二圈少了最左边的一个数字,和最右边的数字。

第四是n%2的细节,如果圈数是奇数,则必有一个元素没有被加入进去,那么在后面判断一下单独加入即可,关于循环为什么是n/2,可以通过举例找规律,例如n=3,就是遍历一次,在后面加入中间元素即可。

关于offset不太好理解:offset的意义在于 结束一圈后 起始位置向后移 结束位置向前移。可以画和n=4或者n=5的矩阵,会比较好理解。offset就是由于要去更向内的一圈,内圈元素更少的地方循环,所以循环的次数变少了

总结:

今天的三道题感觉自己收获了不少,特别是滑动窗口的使用。和解决螺旋矩阵时对一些变量的定义和利用。接下来,我们继续进行算法练习·。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023/9/20总结

maven maven本质是 一个项目管理工具 将项目开发 和 管理过程 抽象成 一个项目对象模型&#xff08;POM&#xff09; POM &#xff08;Project Object Model&#xff09; 项目对象模型 作用 项目构建 提供标准的自动化 项目构建 方式依赖管理 方便快捷的管理项目依赖的资源…

【SpringBoot项目】SpringBoot+MyBatis+MySQL电脑商城

在b站听了袁老师的开发课&#xff0c;做了一点笔记。 01-项目环境搭建_哔哩哔哩_bilibili 基于springboot框架的电脑商城项目&#xff08;一&#xff09;_springboot商城项目_失重外太空.的博客-CSDN博客 项目环境搭建 1.项目分析 1.项目功能:登录、注册、热销商品、用户管…

2023年8月京东户外鞋服市场(京东数据运营)

当前&#xff0c;户外活动的热潮使得户外鞋服市场备受青睐&#xff0c;带动了整个市场的高增长。 根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;今年8月份&#xff0c;京东平台户外鞋服市场的销量为46万&#xff0c;同比增长约25%&#xff1b;销售额为9500万&#xf…

视觉检测系统可以检测太阳能电池片哪些方面的缺陷?

近年来&#xff0c;随着全球工业化进程的不断加快&#xff0c;能源与环境危机成为一个亟待解决的问题。为此&#xff0c;太阳能作为一种清洁可再生的能源&#xff0c;现已被广泛应用于各领域。太阳能电池片作为太阳能转换为电能的核心载体&#xff0c;其质量的好坏决定着电能的…

Cannot find module ‘core-js/modules/es6.regexp.constructor‘

npm run dev 之后报如下错误 解决方法&#xff1a;npm install core-js2 如果超时或者下载时间慢可以尝试 用cnpm install core-js2

【送书】实现可观测性平台的技术要点是什么?

文章目录 实现可观测性平台的技术要点是什么?兼容全域信号量所谓全域信号量有哪些&#xff1f;统一采集和上传工具统一的存储后台自由探索和综合使用数据总结 实现可观测性平台的技术要点是什么? 随着可观测性理念的深入人心&#xff0c;可观测性平台已经开始进入了落地阶段…

爸妈让我放弃百度,选择东软

作者&#xff1a;阿秀 InterviewGuide大厂面试真题网站&#xff1a;https://top.interviewguide.cn 这是阿秀的第「305」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 目前已经是九月下旬了&#xff0c;秋招已经进入中后期了&#xff0c;很多公司已经开启秋招有一段时间了&…

C++实现WebSocket通信(服务端和客户端)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

【postgresql】替换 mysql 中的ifnull()

数据库由mysql 迁移到postgresql&#xff0c;程序在执行查询时候报错。 HINT: No function matches the given name and argument types. You might need to add explicit type casts. CONTEXT: referenced column: ifnull 具体SQL: SELECT ifnull(phone,) FROM c_user p…

mysql限制用户登录失败次数,限制时间

mysql用户登录限制设置 mysql 需要进行用户登录次数限制,当使用密码登录超过 3 次认证链接失败之后,登录锁住一段时间,禁止登录这里使用的 mysql: 8.1.0 这种方式不用重启数据库. 配置: 首先进入到 mysql 命令行:然后需要安装两个插件: 在 mysql 命令行中执行: mysql> INS…

软件项目管理【UML-类图】

前言 UML图有很多种&#xff0c;但是并非必须掌握所有的UML图&#xff0c;才能完整系统分析和设计工作。一般说来&#xff0c;在UML图中&#xff0c;只要掌握类图、用例图、时序图的使用&#xff0c;就能完成大部分的工作。也就是说&#xff0c;掌握UML的20%&#xff0c;就能做…

Vivado中增加源文件界面中各选项的解释

文章目录 官方解释结论总结验证增加单个.v文件增加文件夹Copy sources into project 参考文献 本文对Vivado中增加源文件界面Add or Create Design Sources和Add or Create Smulaton sources中的选项Scan and add RTL include files into project、Copy sources into project和…

影响软文效果的三大因素,一定要牢记

在信息技术发展速度越来越快的今天&#xff0c;企业宣传时已经不再局限于传统的硬广&#xff0c;开始利用软文来提升曝光率&#xff0c;软文作为一种全新的宣传手段&#xff0c;具有覆盖面广、成本低且持续时间长&#xff0c;但是有三大因素稍不注意就会影响软文发布的效果&…

八月份跳槽了,历经华为测开岗4轮面试,不出意外,被刷了...

大多数情况下&#xff0c;测试员的个人技能成长速度&#xff0c;远远大于公司规模或业务的成长速度。所以&#xff0c;跳槽成为了这个行业里最常见的一个词汇。 前几天&#xff0c;我看到有朋友留言说&#xff0c;他在面试华为的测试开发工程师的时候&#xff0c;灵魂拷问三小…

buuctf web [极客大挑战 2019]LoveSQL

又是这样的界面&#xff0c;这糟糕的熟悉感&#xff0c;依旧使用上题套路 用户名&#xff1a; admin or 11# 密码&#xff1a; 1 有一串很像flag的字符&#xff0c;但是很可惜&#xff0c;这不是flag 看了一眼源代码&#xff0c;没有可以跳转的页面 要换个思路了&#xff0c…

C++ -- 学习系列 std::array 容器

1. std::array 是什么&#xff1f; array 容器是 C 11 标准中新增的序列容器&#xff0c;简单地理解&#xff0c;它就是在 C 普通数组的基础上&#xff0c;添加了一些成员函数和全局函数。在使用上&#xff0c;它比普通数组更安全&#xff0c;且效率并没有因此变差。 与数组一…

OmniPlan Pro 4 for Mac:引领项目管理的创新与高效

OmniPlan Pro 4是一款强大且高效的项目管理工具&#xff0c;专为Mac用户设计。它提供了一套综合性的解决方案&#xff0c;帮助用户在Mac上便捷地进行项目规划、追踪和管理。凭借其直观的界面&#xff0c;用户可以快速上手&#xff0c;并且能充分利用这款工具的各种功能。 规划…

企业如何获得用户信赖感,媒介盒子告诉你

互联网和新媒体的快速发展使得内容市场空前繁荣&#xff0c;营销方式也越来越多元化&#xff0c;消费者已经很难被夸张吸睛的营销模式打动&#xff0c;他们更倾向于选择自己信赖的产品&#xff0c;对于企业而言&#xff0c;用户信任是决定企业发展与否的关键因素&#xff0c;产…

自动直播软件开发方案:打造智能化、高效化的直播体验

一、引言 随着社交媒体和互联网的快速发展&#xff0c;直播已经成为了人们互动和传播的重要方式。然而&#xff0c;传统直播存在着人力成本高、内容质量不稳定等问题&#xff0c;因此&#xff0c;开发一款自动直软件成为了解决这些问题的关键。 二、市场需求分析 1…

APP稳定性测试工具:Monkey

一、Monkey 简介 Monkey 是一款 app 的自动化测试工具&#xff0c;monkey 是猴子的意思&#xff0c;所以从原理上说&#xff0c;它的自动化测试就类似猴子一样在软件上乱敲按键&#xff0c;猴子什么都不懂&#xff0c;就爱捣乱。Monkey 原理也是类似&#xff0c;通过向系统发送…