LeedCode刷题---双指针问题(二)

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、盛水最多的容器

题目链接:盛最多水的容器

题目描述

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

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

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

说明:你不能倾斜容器。

示例 1:

输入:[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

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

解法

设两个指针left,right分别指向容器的左右两个端点,此时容器的容积:

       v = (right - left) * min( height[right], height[left])

       容器的左边界为height[left] ,右边界为height[right]

       为了方便叙述,我们假设「左边边界」小于「右边边界」

如果此时我们固定一个边界,改变另一个边界,水的容积会有如下变化形式:

       容器的宽度一定变小。

       由于左边界较小,决定了水的高度。如果改变左边界,新的水面高度不确定,但是一定不会超过右边的柱子高度,因此容器的容积可能会增大。

       如果改变右边界,无论右边界移动到哪里,新的水面的高度一定不会超过左边界,也就是不会超过现在的水面高度,但是由于容器的宽度减小因此容器的容积一定会变小的。

       由此可见,左边界和其余边界的组合情况都可以舍去。所以我们可以(left++跳过这个边界,继续去判断下一个左右边界。

       当我们不断重复上述过程,每次都可以舍去大量不必要的枚举过程,直到left与right相遇。期间产生的所有的容积里面的最大值,就是最终答案。

代码实现

class Solution 
{
public:
    int maxArea(vector<int>& height) 
    {
        int left = 0, right = height.size() - 1, ret = 0;
        while(left<right)
        {
            int v = (min(height[left], height[right]) * (right - left));
            ret = max(ret, v);
            if(height[left] > height[right])
                right--;
            else
                left++;
        }
        return ret;
    }
};

二、有效三角形的个数

题目链接:有效三角形的个数

题目描述

       给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例 1:

输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

示例 2:

输入: nums = [4,2,3,4]
输出: 4

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

解法

解法一(暴力求解)(会超时)

算法思路:

       三层for循环枚举出所有的三元组,并且判断是否能构成三角形。

       虽然说是暴力求解,但是还是想优化一下:

判断三角形的优化:

       如果能构成三角形,需要满足任意两边之和要大于第三边。但是实际上只需让较小的两条边
之和大于第三边即可。

       因此我们可以先将原数组排序,然后从小到大枚举三元组,一方面省去枚举的数量,另一方
面方便判断是否能构成三角形。

解法二(排序+双指针):

算法思路:

       先将数组排序。

       根据「解法一」中的优化思想,我们可以固定一个「最长边」,然后在比这条边小的有序数组中找出一个二元组,使这个二元组之和大于这个最长边。由于数组是有序的,我们可以利用「对撞指针」来优化。

设最长边枚举到1位置,区间[left,right]是位置左边的区间(也就是比它小的区间)︰

如果nums [left] + nums[right] > nums[i]:

       说明[left, right - 1]区间上的所有元素均可以与nums[right]构成比nums[i]大的二元组

       满足条件的有right - left种

       此时right位置的元素的所有情况相当于全部考虑完毕,right-- ,进入下一轮判断。

如果nums [left] + nums[right] <= nums[i] :

       说明left位置的元素是不可能与[left + 1,right]位置上的元素构成满足条件的二元组

       left位置的元素可以舍去,left++进入下轮循环

代码实现

class Solution 
{
public:
    int maxArea(vector<int>& height) 
    {
        int left = 0, right = height.size() - 1, ret = 0;
        while(left<right)
        {
            int v = (min(height[left], height[right]) * (right - left));
            ret = max(ret, v);
            if(height[left] > height[right])
                right--;
            else
                left++;
        }
        return ret;
    }
};

三、查找总价为目标值的两个商品

题目链接:查找总价格为目标值的两个商品

题目描述

       购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。

示例 1:

输入:price = [3, 9, 12, 15], target = 18
输出:[3,15] 或者 [15,3]

示例 2:

输入:price = [8, 21, 27, 34, 52, 66], target = 61
输出:[27,34] 或者 [34,27]

提示:

  • 1 <= price.length <= 10^5
  • 1 <= price[i] <= 10^6
  • 1 <= target <= 2*10^6

解法

a.初始化left ,right分别指向数组的左右两端(这里不是我们理解的指针,而是数组的下标)

b.当left < right的时候,一直循环

     i. 当nums[left] + nums[right] == target时,说明找到结果,记录结果,并且返回;

     ii.当nums[left] + nums[right] < target时:

       对于nums[left]而言,此时nums[right]相当于是nums [left]能碰到的最大值(别忘了,这里是升序数组哈~)。如果此时不符合要求,说明在这个数组里面,没有别的数符合nums[left]的要求了(最大的数都满足不了你,你已经没救了)。因此,我们可以大胆舍去这个数,让 left++,去比较下一组数据;

       那对于nums[right]而言,由于此时两数之和是小于目标值的,nums[right]还可以选择比nums[left]大的值继续努力达到国标值,因此right指针我们按兵不动;

     iii.当nums[left] + nums[right1> target时,同理我们可以舍去nums[right](最小的数都满足不了你,你也没救了)。让right--,继续比较下一组数据,而left指针不变(因为他还是可以去匹配比nums[right]更小的数的)。

代码实现

class Solution 
{
public:
    vector<int> twoSum(vector<int>& price, int target) 
    {
        int left = 0, right = price.size() - 1;
        while(left < right)
        {
            int sum = price[left] + price[right];
            if(sum < target)
                left++;
            else if(sum > target)
                right--;
            else
                return {price[left], price[right]};
        }
        return {0,0};
    }
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

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

相关文章

Nacos下载、启动与使用的保姆级教程!

nacos下载及启动 nacos下载 首先打开nacos官方仓库链接。Nacos发布版本仓库。 点击Tags按钮找到nacos的历史发布的所有版本&#xff0c;点击download。 然后选择需要的下载即可。 后缀为.tar.gz为linux系统上运行的压缩包 后缀为.zip为windows系统上运行的压缩包 zip格式的…

vivado时序方法检查5

TIMING-14 &#xff1a; 时钟树上的 LUT 在时钟树上发现 LUT <cell_name> 。不建议在时钟路径上包含 LUT 单元。 描述 时钟路径上的 LUT 可能导致偏差过大 &#xff0c; 因为时钟必须在穿过互连结构的常规布线资源上进行布线。除偏差过大外 &#xff0c; 这些路径更…

[论文阅读]BEVFusion

BEVFusion BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework BEVFusion&#xff1a;简单而强大的激光雷达相机融合框架 论文网址&#xff1a;BEVFusion 论文代码&#xff1a;BEVFusion 简读论文 论文背景&#xff1a;激光雷达和摄像头是自动驾驶系统中常用的两…

SRC挖掘漏洞XSS

Markdown是一种轻量级标记语言&#xff0c;创始人为约翰格鲁伯&#xff08;John Gruber&#xff09;。它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的 XHTML&#xff08;或者HTML&#xff09;文档。这种语言吸收了很多在电子邮件中已有的纯文本标记的…

App自动化测试持续集成效率提高50%

持续集成是一种开发实践&#xff0c;它倡导团队成员需要频繁的集成他们的工作&#xff0c;每次集成都通过自动化构建&#xff08;包括编译、构建、自动化测试&#xff09;来验证&#xff0c;从而尽快地发现集成中的错误。让正在开发的软件始终处于可工作状态&#xff0c;让产品…

C++STL的string类(一)

文章目录 前言C语言的字符串 stringstring类的常用接口string类的常见构造string (const string& str);string (const string& str, size_t pos, size_t len npos); capacitysize和lengthreserveresizeresize可以删除数据 modify尾插插入字符插入字符串 inserterasere…

模电笔记。。。。

模电 2.8 蜂鸣器 按照蜂鸣器驱动方式分为有源蜂鸣器和无源蜂鸣器 有源的有自己的震荡电路&#xff0c;无源的要写代码控制。 里面有个线圈&#xff0c;相当于电感&#xff0c;储能&#xff0c;通直隔交。 蜂鸣器的参数&#xff1a;额定电压&#xff0c;工作电压&#xff0…

深入理解mysql的explain命令

1 基础 全网最全 | MySQL EXPLAIN 完全解读 1.1 MySQL中EXPLAIN命令提供的字段包括&#xff1a; id&#xff1a;查询的标识符。select_type&#xff1a;查询的类型&#xff08;如SIMPLE, PRIMARY, SUBQUERY等&#xff09;。table&#xff1a;查询的是哪个表。partitions&…

【算法每日一练]-结构优化(保姆级教程 篇4 树状数组,线段树,分块模板篇)

除了基础的前缀和&#xff0c;后面还有树状数组&#xff0c;线段树&#xff0c;分块的结构优化。 目录 分块 分块算法步骤&#xff1a; 树状数组 树状数组步骤&#xff1a; 线段树点更新 点更新步骤&#xff1a; 线段树区间更新 区间更新步骤&#xff1a; 分块 分块算…

【wvp】测试记录

ffmpeg 这是个莫名其妙的报错&#xff0c;通过排查&#xff0c;应该是zlm哪个进程引起的 会议室的性能 网络IO也就20M

业绩超预期,股价却暴跌,MongoDB股票还值得投资吗?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 尽管MongoDB(MDB)本季度的财报超出了预期&#xff0c;并提高了全年预期&#xff0c;但它的股价在财报发布后还是出现了暴跌。 MongoDB截至2023年10月31日的第三财季&#xff0c;收入同比增长了30%&#xff0c;达到了4.329亿…

各大电商平台商品详情API调用(API接口)、淘宝API、京东API、拼多多API、1688API文档案例演示

电商API接口的作用主要表现在以下几个方面&#xff1a; 数据支持&#xff1a;通过开放API接口&#xff0c;其他软件、应用、网站等可以访问电商平台的数据库和功能&#xff0c;利用这些数据提供更丰富的功能和更好的服务。例如&#xff0c;API接口可以收集用户的购物记录、搜索…

第二十一章总结。。

计算机网络实现了堕胎计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是再已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互之间可以交换数据&#xff0c;编写网络应用程序前&#xff0c;首先必须明确网络协议…

状态机的练习:按键控制led灯

设计思路&#xff1a; 三个按键控制led输出。 三个按键经过滤波(消抖)&#xff0c;产生三个按键标志信号。 三个led数据的产生模块&#xff08;流水&#xff0c;跑马&#xff0c;闪烁模块&#xff09;&#xff0c;分别产生led信号。 这六路信号&#xff08;三路按键信号&am…

4种常见的限流算法

限流算法 1、固定窗口 含义&#xff1a; 在一个固定长度的时间窗口内限制请求数量&#xff0c;每来一个请求&#xff0c;请求次数加一&#xff0c;如果请求数量超过最大限制&#xff0c;就拒绝该请求 优点&#xff1a; 实现简单&#xff0c;容易理解。 缺点&#xff1a; ①限流…

Ngxin实现301重定向映射

要实现将abc.love域名映射到http://baidu.com网站&#xff0c;并进行重定向&#xff0c;你需要在Nginx的配置文件中添加一个新的server块&#xff0c;如下所示&#xff1a; server {listen 80;server_name abc.com; #替换成自己的域名&#xff0c;记得要映射到这台服务器&…

element UI改写时间线组件为左右分布

2023.12.4今天我学习了如何使用element的时间线组件&#xff0c;效果如&#xff1a; 代码如下&#xff1a;&#xff08;关键代码 v-if"item.send_type"&#xff09;判断左右分布情况。因为如果没有这个判断的话&#xff0c;其实会两边都有显示。可以用一个判断表示0显…

OpenEuler_22.03升级mongdb到7.0.4

使用命令&#xff1a;lscpu&#xff0c;查看cpu架构为aarch64为arm架构的一种执行状态。 所以我们直接下载arm的包安装即可。无需自己编译源码。 下载地址&#xff1a;https://www.mongodb.com/try/download/community 下载解压 wget https://fastdl.mongodb.org/linux/mong…

使用腾讯逆地理位置编码获取地理位置信息

文章目录 前言一、代码二、开放平台操作步骤1.开发者认证2.创建应用 总结 前言 最近项目中一个发帖的功能需要获取当前用户的发帖位置&#xff0c;由于是在APP内部使用&#xff0c;而且APP是使用uniApp开发的&#xff0c;所以在使用开放平台的SDK选用上有些麻烦&#xff0c;有…

echarts环形饼图

效果示例 代码汇总 pieCharts() {let data [];const providerResult [{name: 智诺, value: 23},{name: 海康, value: 5},{name: 大华, value: 5}, {name: 云科, value: 23},{name: 四信, value: 22},{name: 九物, value: 22}]let charts echarts.init(document.getElemen…