算法刷题Day2 | 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

目录

  • 0 引言
  • 1 有序数组列表
    • 1.1 我的题解(双指针)
    • 1.2 根据官方解题修改后
  • 2 长度最小的子数组
    • 2.1 我的题解
    • 2.2 官方滑动窗口(双指针)题解
  • 3 螺旋矩阵
    • 3.1 我的题解

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

0 引言

1 有序数组列表

  • 🎈 文档讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html
  • 🎈 视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep
  • 🎈 做题状态:没有抓住顺序排序的精髓,导致解题思路不明确。现在知道双指针不仅可以从一头遍历,也可以同时从两头遍历

1.1 我的题解(双指针)

这道题主要利用了数组顺序排序的特性,基于此可以得知数组平方后的最大数一定在数组的两端。所以只需要从两端开始比较找出最大的数,然后插入到新数组的最后一位即可得到排序好的新数组。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        // 平方后的数肯定大于等于0
        vector<int> result;
        int leftIndex, rightIndex;
        leftIndex = 0; rightIndex = nums.size() - 1;

        // 双指针法基于数组非递减顺序的特点,可知平方后的最大数在数组的两端
        // 所以从两头往中间遍历依次把最大数插入到新的数组中,即可得到答案。
        while (leftIndex <= rightIndex)
        {
            // 当左侧数的绝对值更大时插入左侧的数据,leftIndex加一
            if (abs(nums[leftIndex]) >= abs(nums[rightIndex]))
            {
                result.insert(result.begin(), abs(nums[leftIndex] * abs(nums[leftIndex])));
                leftIndex++;
            }
            // 当右侧数的绝对值更大时插入右侧的数据,rightIndex减一
            else
            {
                int temp = abs(nums[rightIndex] * abs(nums[rightIndex]));
                result.insert(result.begin(), temp);
                rightIndex--;
            }
        }

        return result;
    }
};

1.2 根据官方解题修改后

但是我这个题解还有很多不足的地方,例如新数组的插入操作,使用的是Insert,这个函数的时间复杂度是 n,因为是从头插入新的元素,所以每次都会导致其他元素全部向后移动一位。

通过官方题解,可以得知。直接将新数组元素个数确定,然后采用索引的方式从后往前给新数组赋值,这样可以节省很多的时间。

class Solution {
public:
   vector<int> sortedSquares2(vector<int>& nums) {
       // 平方后的数肯定大于等于0
       int leftIndex, rightIndex, insertIndex;
       leftIndex = 0; insertIndex = rightIndex = nums.size() - 1;
       vector<int> result(nums.size());

       while (leftIndex <= rightIndex)
       {
           if (abs(nums[leftIndex]) >= abs(nums[rightIndex]))
           {
               result[insertIndex] = abs(nums[leftIndex] * abs(nums[leftIndex]));
               leftIndex++;
           }
           else
           {
               result[insertIndex] = abs(nums[rightIndex] * abs(nums[rightIndex]));
               rightIndex--;
           }
           insertIndex--;
       }

       return result;
   }
};

2 长度最小的子数组

  • 🎈 文档讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
  • 🎈 视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
  • 🎈 做题状态:不看视频和文档直接写出来了(因该还是学习了之前的双指针思想有所启发),但是代码还是有很多地方需要优化

2.1 我的题解

主要就是通过左右两个索引来对该范围内的数组进行相加统计。但是我的代码存在很多特殊条件的判断,不够精简。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = nums.size() + 1, leftIndex = 0, rightIndex = 0;
        int sum = nums[0];

        // 当rightIndex大于数组长度时才结束遍历
        while (rightIndex < nums.size() && leftIndex < nums.size())
        { 
            // 当sum的合小于目标值,rightIndex加一
            if (sum < target)
            {
                rightIndex++;
                if (rightIndex >= nums.size())
                {
                    // 处理特殊情况
                    if (result == nums.size() + 1)
                    {
                        return 0;
                    }
                    return result;
                }
                sum = sum + nums[rightIndex];
            }
            // 当sum大于等于target时,将result和 (rightIndex-leftIndex)+1 作比较,取最小的值
            // 此时leftIndex要减一
            else
            {
                result = min(result, rightIndex - leftIndex + 1);
                // 如果result等于1时,直接返回
                if (result == 1) return result;
                
                // 先减去左边索引的值,然后在将坐标索引向右移动一位
                sum = sum - nums[leftIndex];
                leftIndex++;
            }
        }

        // 处理特殊情况
        if (result == nums.size() + 1)
        {
            return 0;
        }
        return result;
    }
};

2.2 官方滑动窗口(双指针)题解

官方的滑动窗口和我写的有细微区别,但是对于 sum 的操作都是一样,当rightIndex向右移动是需要 sum加,让leftIndex向右移动时,需要sum减去值。

class Solution {
public:
    int minSubArrayLen(int s, 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 >= s) {
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

3 螺旋矩阵

  • 🎈 文档讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
  • 🎈 视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/?vd_source=d499e7f3a8e68e2b173b1c6f068b2147
  • 🎈 做题状态:主要是循环条件的确定需要慢慢调试

3.1 我的题解

  • 思路:根据n来计算需要遍历的圈数,n为1时0圈,n为2时一圈,n为3时一圈。圈数为 n/2 然后取整。然后再根据四个赋值的方向制作四个循环。最后当n为奇数时,需要手动给中间的数赋值。
  • 难点:每次循环时,条件的确定。时刻记住数组的最大的下标和数组元素个数相差1。
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n));
        int number = 1;
        int i = 0;

        // 遍历的圈数确定,圈数 = n/2然后取整 (n为1时0圈,n为2时一圈,n为3时一圈)
        for ( ; i < n/2; i++)
        {
            // 每遍历完一圈后,行的区间要从首尾各减去一,列的区间也要从首尾各减去一
            int j = i;

            for (j = i; j < (n - i); j++)
            {
                // 第一行
                result[i][j] = number;
                number++;
            }
            for (j = i+1; j < (n - i); j++)
            {
                // 最后一列,n-1 对应最后一列
                result[j][n - 1 - i] = number;
                number++;
            }
            for (j = i+1; j < (n - i); j++)
            {
                // 最后一行,从最后一列开始遍历,n-1是最后一列
                result[n - 1 - i][n - 1 - j] = number;
                number++;
            }
            // 第一列遍历,少一个元素,需要注意
            for (j = i+1; j < (n - i) - 1; j++)
            {
                // 第一列,从最后一行向上
                result[n - 1 - j][i] = number;
                number++;
            }
        }

        // 当n为奇数时,需要手动给中心点赋值
        if (n%2 != 0)
        {
            result[i][i] = number;
        }
        

        // 遍历完后返回结果
        return result;
    }
};

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

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

相关文章

CXYGZL实现钉钉、飞书和微信全面覆盖!!!

非常欣慰能在这里与大家分享&#xff0c;CXYGZL已圆满实现多端互通的目标&#xff01;&#xff01;&#xff01; 无论您是在手机、电脑还是平板上使用钉钉、企微还是飞书&#xff0c;只需将CXYGZL轻松集成到您的办公软件中&#xff0c;即可实现无缝审批处理各项任务&#xff0c…

FreeRTOS_day2

作业&#xff1a;1.使用ADC采样光敏电阻数值&#xff0c;如何根据这个数值调节LED灯亮度。 2.总结DMA空闲中断接收数据的使用方法 打开DAM,允许接收外部设备数据&#xff0c;调用中断接收回调函数

王道机试C++第 3 章 排序与查找:排序问题 Day28(含二分查找)

查找 查找是另一类必须掌握的基础算法&#xff0c;它不仅会在机试中直接考查&#xff0c;而且是其他某些算法的基础。之所以将查找和排序放在一起讲&#xff0c;是因为二者有较强的联系。排序的重要意义之一便是帮助人们更加方便地进行查找。如果不对数据进行排序&#xff0c;…

热插拔更换ESXI宿主机系统硬盘导致紫屏故障案例一则

关键词 vmware、esxi5.5raid、热插拔、紫屏 华为 CH121V3刀片、SSD硬盘 There are many things that can not be broken&#xff01; 如果觉得本文对你有帮助&#xff0c;欢迎点赞、收藏、评论&#xff01; 一、问题现象 现网vmware云平台一台华为E9000刀箱CH121V3刀片服务…

面试经典150题——环形链表

Suffering, for the weak is the tomb of death, and for the strong is the soil of germinal ambition.​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 这个题目就是判断一个链表有没有环&#xff0c;其实我们之讲过一个题目&#xff0c;就实现了判断链表有没有环的步骤&a…

1 数据分析概述与职业操守 (3%)

1、 EDIT数字化模型 E——exploration探索 &#xff08;是什么&#xff09; 业务运行探索&#xff1a;探索关注企业各项业务的运行状态、各项指标是否合规以及各项业务的具体数据情况等。 D——diagnosis 诊断 (为什么) 问题根源诊断&#xff1a;当业务指标偏离正常值时&…

C#,哈夫曼编码(Huffman Code)压缩(Compress )与解压缩(Decompress)算法与源代码

David A. Huffman 1 哈夫曼编码简史&#xff08;Huffman code&#xff09; 1951年&#xff0c;哈夫曼和他在MIT信息论的同学需要选择是完成学期报告还是期末考试。导师Robert M. Fano给他们的学期报告的题目是&#xff0c;寻找最有效的二进制编码。由于无法证明哪个已有编码是…

GCN 翻译 - 2

2 FAST APROXIMATE CONVOLUTIONS ON GRAPHS 在这一章节&#xff0c;我们为这种特殊的的图基础的神经网络模型f(X, A)提供理论上的支持。我们考虑一个多层的图卷积网络&#xff08;GCN&#xff09;&#xff0c;它通过以下方式进行层间的传播&#xff1a; 这里&#xff0c;是无…

Spring事务注解@Transactional的流程和源码分析

Spring事务简介 Spring事务有两种方式&#xff1a; 编程式事务&#xff1a;编程式事务通常使用编程式事务管理API实现&#xff0c;比如Spring提供的PlatformTransactionManager接口&#xff0c;使用它操控事务。声明式事务&#xff1a;注解式事务使用AOP&#xff08;面向切面…

【24春招/简历】如果技术和学历不行,如何包装自己在春招中占得先机?突出你的亮点!

面试讲什么 学历&#xff1a; 行情 要美化&#xff08;吹牛&#xff09; 面试很好 技术能力 让面试官知道你会哪些技术&#xff0c;尽量细节 “熟悉spring” > ioc流程&#xff0c;Bean的生命周期&#xff0c;循环依赖&#xff0c;常见注解 熟悉redis > 缓存穿透&…

【Java设计模式】八、装饰者模式

文章目录 0、背景1、装饰者模式2、案例3、使用场景4、源码中的实际应用 0、背景 有个快餐店&#xff0c;里面的快餐有炒饭FriedRice 和 炒面FriedNoodles&#xff0c;且加配菜后总价不一样&#xff0c;计算麻烦。如果单独使用继承&#xff0c;那就是&#xff1a; 类爆炸不说&a…

Django项目的部署——之环境的重建

Django项目的部署 版本对应 Django 2.0.6 可以匹配mysql5.6.48版本&#xff0c;和mysql5.7.7版本一块用会报错。 其它版本未测试。 创建新的虚拟环境 根据项目版本安装对应的Python包。比如项目开发时用的是python-3.6.4&#xff0c;则安装该版本&#xff0c;并配置环境变量…

【智能家居】东胜物联ODM定制ZigBee网关,助力能源管理解决方案商,提升市场占有率

背景 本文案例服务的客户是专业从事智能家居能源管理的解决方案商&#xff0c;其产品与服务旨在帮助用户监测、管理和优化能源消耗&#xff0c;以提高能源使用效率。 随着公司的扩张&#xff0c;为了增加市场占有率&#xff0c;他们希望找到更好的硬件服务支持&#xff0c;以…

leetcode 3.6

Leetcode hot 100 一.矩阵1.旋转图像 二.链表1. 相交链表2.反转链表3.回文链表4.环形链表5.环形链表 II 一.矩阵 1.旋转图像 旋转图像 观察规律可得&#xff1a; matrix[i][j] 最终会被交换到 matrix [j][n−i−1]位置&#xff0c;最初思路是直接上三角交换&#xff0c;但是会…

学习clickhouse 集群搭建和分布式存储

为什么要用集群 使用集群的主要原因是为了提高系统的可扩展性、可用性和容错性。 可扩展性&#xff1a;当单个节点无法处理增加的负载时&#xff0c;可以通过添加更多的节点到集群来增加处理能力。这使得系统可以处理更大的数据量和更高的查询负载。可用性&#xff1a;在集群…

Java项目:41 springboot大学生入学审核系统的设计与实现010

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本大学生入学审核系统管理员和学生。 管理员功能有个人中心&#xff0c;学生管理&#xff0c;学籍信息管理&#xff0c;入学办理管理等。 学…

解决 RuntimeError: “LayerNormKernelImpl“ not implemented for ‘Half‘

解决 RuntimeError: “LayerNormKernelImpl” not implemented for ‘Half’。 错误类似如下&#xff1a; Traceback (most recent call last): File “cli_demo.py”, line 21, in for results in webglm.stream_query(question): File “/root/WebGLM/model/modeling_webgl…

CTP-API开发系列之三:柜台系统简介

CTP-API开发系列之三&#xff1a;柜台系统简介 CTP-API开发系列之三&#xff1a;柜台系统简介中国金融市场结构---交易所柜台系统通用柜台系统极速柜台系统主席与次席 CTP柜台系统CTP组件名称对照表CTP柜台系统程序包CTP柜台系统架构图 CTP-API开发系列之三&#xff1a;柜台系统…

基于Yolo5模型的动态口罩佩戴识别安卓Android程序设计

禁止完全抄袭&#xff0c;引用注明出处。 下载地址 前排提醒&#xff1a;文件还没过CSDN审核&#xff0c;GitHub也没上传完毕&#xff0c;目前只有模型的.pt文件可以下载。我会尽快更新。 所使用.ptl文件 基于Yolo5的动态口罩佩戴识别模型的pt文件资源-CSDN文库 项目完整文…

信息抽取技术:电商领域的智能化革命与市场策略优化

一、引言 在当今快速发展的互联网电商领域&#xff0c;信息抽取技术的应用已经成为商家优化供应链、降低成本、提高响应速度的关键手段。随着消费者需求的日益多样化和个性化&#xff0c;电子商务平台需要更高效、智能的数据处理能力来应对市场的挑战。从供应商管理到库存优化…