【算法与数据结构】【数组篇】【题11-题15】

系列文章

本人系列文章-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/handsomethefirst/article/details/138226266?spm=1001.2014.3001.5502


1.数组基本知识点

1.1概念

数组就是一个集合。数组会用一些名为索引的数字来标识每项数据在数组中的位置,且在大多数编程语言中,索引是从 0 算起的。我们可以根据数组中的索引,快速访问数组中的元素。

数组中的元素在内存中是连续存储的,且每个元素占用相同大小的内存。

1.2 相关操作的时间复杂度和空间复杂度

访问元素时间复杂度都是O(1),空间复杂度O(1),因为对于固定大小的数组,访问时间不随数组大小而变化。通过下标可直接访问。

修改元素:时间复杂度O(1),空间复杂度O(1),与n无关,通过下标可直接修改

插入元素和删除元素:时间复杂度O(1),空间复杂度O(1),插入和删除元素都需要移动后面的元素,因此随n变化。

 题11 最大连续1的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

思路:
第一步:遍历数组,如果值等于1,则number加1,然后每次更新之前number中最大的那个
第二步:如果值不等于1,则重置number,开始重新计数。

 代码案例

class Solution
{
public:int findMaxConsecutiveOnes(vector<int> &nums){int size = nums.size();int number = 0;int returnnumber = 0;for (int first = 0; first < size; first++){if (nums[first] != 1) //如果值不是1,则重新记录数量{number = 0;}else 如果值是1,则数量+1{number++;}returnnumber = max(returnnumber, number);//每次更新最大连续数量的值}return returnnumber;}
};

题12 长度最小的子数组

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

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

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

 思路:

首先需要查找子数组,所以不能排序此数组。因为需要找到子数组的头和尾部,思路可以靠近双指针。

第一次滑动:

第一次滑动达到目标 2+3+1+2=8

    2   3   1   2   4   3
    s             q

第一次尝试收缩发现 8-2< 7,则无法收缩。此时的长度为4,代表nums[0]满足条件的最小区间范围。


第2次滑动:

快指针继续向前,第二次达到目标 2+3+1+2+4=12

    2   3   1   2   4   3
                     q

第二次尝试收缩发现 10>7,可以收缩。

    2   3   1   2   4   3
         s             q

此时的长度也是4,代表nums[1]满足条件的最小区间范围。

再次尝试收缩, 7=7,可以收缩。

    2   3   1   2   4   3
              s        q

此时的长度是3,代表nums[2]满足条件的最小区间范围。

然后无法再次收缩了,此时nums[0],nums[1],nums[2]满足的最小区间范围。

第三次滑动:

快指针继续向前,第三次达到目标, 1+2+4+3>=7

    2   3   1   2   4   3
              s             q

然后尝试收缩,收缩成功, 10-1>=7

    2   3   1   2   4   3
                   s        q

此时的长度是3,代表nums[3]满足条件的最小区间范围。

然后继续尝试收缩,收缩成功,9-2=7

    2   3   1   2   4   3
                        s   q

此时的长度是2,代表nums[4]满足条件的最小区间范围。

此时quick走到了末尾,然后能收缩的都收缩了,代表nums[4]以后的都无法满足大于等于目标值的最小区间范围的条件。

代码案例

class Solution
{
public:int minSubArrayLen(int target, vector<int> &nums){int size = nums.size();int slow = 0;  // 初始化慢指针int quick = 0; // 初始化快指针int sum = 0;   // 前缀和int returnlength = size + 1;for (; quick < size; quick++) {sum = sum + nums[quick]; // 对前面的子数组进行求和if (sum >= target)       // 当前面的和小于目标值的时候,无法收缩,当和大于目标值的时候,才能收缩。{while ((sum - nums[slow]) >= target)//尝试缩小字数组区间{sum = sum - nums[slow];slow++;}returnlength = min(returnlength, quick - slow + 1);}}return returnlength == size + 1 ? 0 : returnlength;//如果所有的和都小于target,则返回0}
};

题13 盛最多的水

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

 作题思路:

第一步:首先分析,最大的水的容量应该是Value =长*宽。那么长=(quick -slow)宽=min(height[quick],height[slow]),所以很明显,此题应该用双指针。通常双指针有两种用法。第一种是一个指向头,一个指向尾部,相反方向移动。第二种是两个都指向头,同方向移动。因此此题也有两种做法。

法一:

双指针,同方向移动。

从height[0]开始,遍历其后值和height[0]形成的大小,然后求最大值。

然后继续从height[1]开始,遍历其后值和height[0]形成的大小,然后求最大值。

缺点:

时间复杂度为N的平方。

法一代码案例:

class Solution
{
public:int maxArea(vector<int> &height){int returnvalue = 0;//返回的最大值int slow = 0;//初始化慢指针int size = height.size();for (; slow < size - 1; slow++)//慢指针遍历{for (int quick = slow + 1; quick < size; quick++)//快指针遍历{int x = quick - slow;//获取长int y = min(height[quick], height[slow]);//获取宽returnvalue = max(returnvalue, x * y);//更新最大值}}return returnvalue;}
};

法二思路:

首先此题相当于找出任何两个y轴和x轴形成的长方形面积最大。那么双指针首先,就需要包含所有的可以作为长方形边界的范围。即

第一步:初始化慢指针slow指向头的位置,初始化快指针quick指向末尾的位置。

第二步:计算此时长方型的最大面积,那么此时长是x=quick -slow,y的值是min(height[quick], height[slow])。

第三步:移动指针,那么如何移动呢?假设,此时数组长度是5,height[quick]是6,height[slow]是1,首先如果移动较大的值,即我们放弃较大的值作为长方形的边界,

那么有以下三种情况:

1.如果height[quick-1]的值>=6,那么新的长方形,此时长是4,宽仍然是height[slow]的,此时

新的长方形最大面积是必然小于前一个值的。

2.如果height[slow]<height[quick-1]<6,那么新的长方形,此时长是4,宽仍然是height[slow]的,此时新的长方形最大面积是必然小于前一个值的。

3.如果height[quick-1]<height[slow],那么新的长方形,此时长是4,宽是height[quick-1],此时新的长方形最大面积是必然小于前一个值的。

那么此时我们就知道,当我们移动较大的边界值时候。其值永远都是更小的。

此时我们再分析一下移动较小的值。有以下几种情况。

1.如果height[slow+1]<=height[slow],则此时长从5变为4,则最大面积变小。

2.如果height[slow+1]>height[slow],则此时有可能新的长方形面积更大。

所以我们只能移动较小的那个边界值。

第四步:每次移动获取的值和最大值作比较,保留最大值。

第五步:当左边界和右边界重合时,说明所有可能比之前的长方形面积更大的都计算完了。

法二代码案例:

class Solution
{
public:int maxArea(vector<int> &height){int returnvalue = 0;           // 返回的最大值int slow = 0;                  // 初始化慢指针指向头的位置int quick = height.size() - 1; // 初始化快指针指向末尾的位置while (slow < quick){returnvalue = max(returnvalue, (quick - slow) * min(height[quick], height[slow]));if (height[quick] >= height[slow]){slow++;//如果右边界值大于左边界值,则移动左边界值}else{quick --;//如果右边界值小于左边界值,则移动右边界值}}return returnvalue;}
};

题14 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

 思路:

首先对于数组的操作,能先排序就排序,能双指针就双指针。

此题也可以理解为:

遍历每一个值,然后从剩下的所有值中找两个其他的值,其三个的和等于0。

第一步:对数组排序,如果前三个最小的之和大于0,因为数组此时是递增的,那么后面不可能等于0,则返回。

假设此时数组长度是5。

第二步:固定第一个数字nums[0],此时我们的条件就变成了在剩下不包括nums[0]的数组中找到两个值,这两个值的和是-nums[0]。而此时是已经排序的数组。

第三步:让慢指针指向nums[1]的位置,快指针指向nums数组的尾部nums[4],然后判断nums[1]+nums[4] 和(0-nums[i])的大小。如果大于(0-nums[i]),则尾指针向左移动,如果小于则头指针向右移动。如果等于,则满足条件,此时如果没有重复值,则头指针向右移动并且尾指针向左移动。如果有重复值,则需要跳过。

想一想,如果此时满足条件的值是(-1,0,1),而nums[3]也等于-1,如果没跳过,则出现两个(-1,0,1),不满足条件。

第四步:然后遍历第二个元素,如果第二个等于第一个,则跳过,遍历下一个。然后重复第二步到第四步。

代码案例:

class Solution
{
public:vector<vector<int>> threeSum(vector<int> &nums){vector<vector<int>> returnvector;if (nums.size() < 3){return returnvector;}sort(nums.begin(), nums.end());if (nums[0] + nums[1] + nums[2] > 0){return returnvector;}for (int i = 0; i < nums.size() - 2; i++){if (i > 0 && nums[i] == nums[i - 1])continue;// 跳过重复的元素int slow = i + 1;//慢指针指向不要nums[i]的数组的头int quick = nums.size() - 1;慢指针指向不要nums[i]的数组的尾while (slow < quick){int sum = nums[slow] + nums[quick] + nums[i];if (sum == 0)//当值相等的时候,则说明找到了{returnvector.push_back({nums[i], nums[slow], nums[quick]});while (slow < quick && nums[slow] == nums[slow + 1])slow++; // 跳过重复的元素while (slow < quick && nums[quick] == nums[quick - 1])quick--; // 跳过重复的元素slow++;quick--;}else if (sum > 0)//当值大于0的时候,则说明我们我们需要移动数组尾端,让值变小一点{quick--;}else if (sum < 0)//当值小于0的时候,则说明我们我们需要移动数组头端,让值变大一点{slow++;}}}return returnvector;}
};

题15 最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

示例 2:

输入:nums = [0,0,0], target = 1
输出:0

 思路:

首先对于数组的操作,能先排序就排序,能双指针就双指针。

此题也可以理解为:

遍历每一个值,然后从剩下的所有值中找两个其他的值,其三个的和减去target的值的绝对值最小。

第一步:对数组进行排序,假如此时数组是nums=[-1,2,1,-4],排序后是[-4,-1,1,2]

第二步:因为要遍历所有值,所以第一次循环先挑选nums[0],然后,就变成了在[-1,1,2]中,选择任意两个值,判断三个的和减去target的值的绝对值最小。

第三步:慢指针指向-1,快指针指向2,此时判断nums[0]+nums[slow]+nums[quick] -target的值。

1.如果A[0]+A[slow]+A[quick] -target =0,则直接返回sum = target。

2.如果A[0]+A[slow]+A[quick] -target >0, 尾指针得向左移动 ,如果前三个和大于taraget,则说明要找到下一个更小的。这样可能更靠近target。此时尾指针向左移动,此时需要计算temp - target的绝对值和上一个绝对值的大小,如果当前三个数和的绝对值小于之前的绝对值,则更新sum。

3.如果前三个和小于taraget,则说明要找到更大的。这样可能更靠近target。此时头指针向右移动,此时需要计算temp - target的绝对值和上一个绝对值的大小,如果当前三个数和的绝对值小于之前的绝对值,则更新sum。

此时我们在第一次循环中就找到了以第一个元素为首的与target距离最近的三个数的和。

第二次循环继续重复第二步和第三步,这样就找出了第二个数组为首的三个数,与target距离最近的。依次遍历就找到了所有的子集中与与target距离最近的。

 代码案例:

class Solution
{
public:int threeSumClosest(vector<int> &nums, int target){int sum = 0;int closevalue = INT32_MAX;//初始化为做大值,因为后面要取minsort(nums.begin(), nums.end()); //排序for (int first = 0; first < nums.size() - 2; first++){int slow = first + 1;int quick = nums.size() - 1;while (slow < quick){int temp = nums[first] + nums[slow] + nums[quick];//计算前三个的和if (temp - target == 0)//如果等于taraget,则直接返回{return temp;}else if (temp - target > 0) //如果前三个和大于taraget,则说明要找到下一个更小的。这样可能更靠近target。此时尾指针向左移动,//此时需要计算temp - target的绝对值和上一个绝对值的大小,如果当前三个数和的绝对值小于之前的绝对值,则更新sum{if (abs(temp - target) < closevalue){closevalue = min(abs(temp - target), closevalue);sum = temp;}quick--;}else if (temp - target < 0){if (abs(temp - target) < closevalue)//如果前三个和小于taraget,则说明要找到更大的。这样可能更靠近target。此时头指针向右移动,//此时需要计算temp - target的绝对值和上一个绝对值的大小,如果当前三个数和的绝对值小于之前的绝对值,则更新sum{closevalue = min(abs(temp - target), closevalue);sum = temp;}slow++;}}}return sum;}
};

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

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

相关文章

机器学习-- 如何清洗数据集

文章目录 引言&#xff1a;数据清洗的具体步骤数据清洗的具体方法和示例1. 处理缺失值2. 去除重复数据3. 修正数据格式4. 处理异常值5. 标准化和归一化6. 处理不一致的数据7. 转换数据类型8. 数据集成 总结 引言&#xff1a; 数据清洗是数据处理和分析的关键步骤&#xff0c;旨…

2024/6/11 英语每日一段

They found that, regardless of culture, greater mental well-being is linked with feeling emotions that we believe are appropriate to our situation, rather than just having positive emotions regardless of context--“feeling right” as opposed to “feeling g…

什么是电表无人抄表?

1.电表无人抄表&#xff1a;智能时代的新式计量方法 随着科技的发展的迅猛发展&#xff0c;传统电表抄表方法正被一种全新的、高效率的方式所替代——电表无人抄表。这类技术的普及&#xff0c;不仅提升了电力行业的经营效率&#xff0c;同时也为用户增添了更贴心的服务。 2.…

从零开始手把手Vue3+TypeScript+ElementPlus管理后台项目实战九(整体布局02)

使用el-menu和el-sub-menu及el-menu-item导航 src/layout目录下新增components目录&#xff0c;components目录下新增PageSidebar.vue 代码基本思想为&#xff1a;读取router中定义的routes数组&#xff0c;渲染绑定到el-menu。 el-menu和el-sub-menu及el-menu-item的区别&…

SprringCloud Gateway动态添加路由不重启

文章目录 前言&#xff1a;一、动态路由必要性二、SpringCloud Gateway路由加载过程RouteDefinitionLocator接口PropertiesRouteDefinitionLocator类DiscoveryClientRouteDefinitionLocatorInMemoryRouteDefinitionRepositoryCompositeRouteDefinitionLocator类CachingRouteDef…

【话题】程序员应该有什么职业素养

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景职业素养的重要性职业素养的核心1.1 承诺与责任感1.2 沟通与团队合作1.3 学习与持续进步 态度和价值观的作用2.1 诚实和诚信2.2 责任和自我管理2.3 尊重和多样性 职…

Linux crontabs定时执行任务

文章目录 前言一、安装二、服务1. 启动crond服务2. 关闭crond服务3. 重启crond服务4. 设置crond开机启动5. 禁用crond开机启动6. 查看crond是否开机启动7. 重新载入配置8. 查看crond运行状态 三、使用1. 查看当前用户的crontab2. 编辑用户的crontab3. 删除用户的crontab的内容 …

JEPaaS 低代码平台 j_spring_security_check SQL注入漏洞复现

0x01 产品简介 JEPaaS是一款优秀的软件平台产品,可视化开发环境,低代码拖拽式配置开发,操作极其简单,可以帮助解决Java项目80%的重复工作,让开发更多关注业务逻辑,大大提高开发效率,能帮助公司大幅节省人力成本和时间成本,同时又不失灵活性。适用于搭建 OA、ERP、CRM、…

100v 高耐压ldo 高压三端稳压芯片

100v 高耐压ldo 高压三端稳压芯片

python数据分析-量化分析

一、研究背景 随着经济的发展和金融市场的不断完善&#xff0c;股票投资成为了人们重要的投资方式之一。汽车行业作为国民经济的重要支柱产业&#xff0c;其上市公司的股票表现备受关注。Fama-French 三因子模型是一种广泛应用于股票市场的资产定价模型&#xff0c;它考虑了市场…

高效处理风电时序数据,明阳集团的 TDengine 3.0 应用实录

作为全国 500 强企业&#xff0c;明阳集团在风电行业拥有领先实力。目前全球超过 800 个项目采用明阳各种型号风电机组&#xff0c;安装数量超过 15000 台。每台风电机组配备数百至上千个监测点&#xff0c;生成的时序数据每秒一条&#xff0c;每天产生亿级以上的数据量。这些数…

IPv6 ND 协议功能概述

ND 协议功能概述 ND&#xff08;Neighbor Discovery&#xff0c;邻居发现&#xff09;协议是 IPv6 的一个关键协议&#xff0c;它综合了 IPv4 中的 ARP&#xff0c;ICMP 路由发现和 ICMP 重定向等协议&#xff0c;并对它们做了改进。 作为 IPv6 的基础性协议&#xff0c;ND 协…

AI 定位!只需一张图片就能找到你,锁定具体位置!精确到经纬度

你能猜到这张自拍的拍摄地点吗?别小瞧了AI的能力,答案可能会让你吓一跳。 这事交给现在的AI来处理&#xff0c;它只需要“看”一眼&#xff0c;就能把照片里的“底裤都给扒出来”&#xff1a; 美国&#xff0c;加利福尼亚州&#xff0c;旧金山机场洗手间&#xff0c;93号登机口…

关于Ubuntu24.04嘉立创EDA无法启动的问题

关于Ubuntu24.04嘉立创EDA无法启动的问题 查看无法启动原因解决办法1解决办法2 查看无法启动原因 在终端使用启动文件命令报错 解决办法1 输入如下命令可以正常启动 ./lceda-pro --no-sandbox 解决办法2 找到desktop文件进行修改 cd /usr/share/applications sudo vim lce…

HTML制作一个日蚀的动画特效

大家好&#xff0c;今天制作一个日蚀动画特效&#xff01; 先看具体效果&#xff1a; 使用一个逐渐扩大的圆形阴影来模拟月亮遮挡太阳的效果。使用了CSS的keyframes动画和border-radius属性来创建一个简单的圆形阴影效果。 HTML <!DOCTYPE html> <html lang"e…

[Cloud Networking] Layer 2 Protocol

文章目录 1. STP / RSTP / MSTP Protocol1.1 STP的作用1.2 STP 生成树算法的三个步骤1.3 STP缺点 2. ARP Protocol3. MACSEC 1. STP / RSTP / MSTP Protocol 1.1 STP的作用 消除二层环路&#xff1a;通过阻断冗余链路来消除网络中可能存在的环路链路备份&#xff1a;当活动链…

DC/AC电源模块:为物联网设备提供可靠的电力支持

BOSHIDA DC/AC电源模块&#xff1a;为物联网设备提供可靠的电力支持 DC/AC电源模块是物联网设备中非常重要的组成部分之一&#xff0c;它为设备提供稳定、可靠的电力支持。在物联网应用中&#xff0c;设备通常需要通过无线网络与其他设备或云平台进行通信&#xff0c;而这些设…

Photoshop中颜色与色调的调整

Photoshop中颜色与色调的调整 Photoshop中的颜色模式RGB模式灰度模式位图模式索引模式CMYK模式Lab模式 Photoshop中的颜色/色调调整命令颜色/色调调整命令的分类亮度/对比度调整命令色阶命令曲线命令曝光度命令自然饱和度命令色相/饱和度命令色彩平衡命令照片滤镜调整命令通道混…

【个人博客搭建】(23)购买服务器、域名、备案

1、服务器主要是为了有一个公网的IP地址&#xff0c;方便我们可以通过网络随时访问 2、域名是对IP地址的一个替代。简单说IP地址可能不方便记忆&#xff0c;但是自己配置的域名会简单些&#xff0c;另外暴露IP地址也不安全。(虽然也能通过域名找到IP) 3、备案。这是政策。简单所…

运营商三要素核验-手机号实名认证接口-运营商三要素核验接口

手机号三元素实名认证&#xff0c;通过手机号、真实姓名、身份证号来校验三者是否一致。支持三大运营商携号转网查询&#xff0c;姓名、手机号、身份证号码三项验证是否一致&#xff1b;服务器毫秒级响应&#xff0c;信息验证科学严谨&#xff0c;数据安全可靠。 更新周期&…