优选算法精品课--双指针算法(2)

embedded/2024/12/29 5:48:58/

双指针算法(2)

  • 1、有效三角形的个数
    • 1.1 题目解析
    • 1.2 思路解析
    • 1.3 代码实现
  • 2、和为s的两个数
    • 2.1 题目解析
    • 2.2 思路解析
    • 2.3 代码实现
  • 3、三数之和
    • 3.1 题目解析
    • 3.2 思路解析
    • 3.3 代码实现
  • 4、四数之和
    • 4.1 题目解析
    • 4.2 思路解析
    • 4.3 代码实现
  • 5 总结

1、有效三角形的个数

题目链接:
https://leetcode.cn/problems/valid-triangle-number/

1.1 题目解析

在这里插入图片描述
题目的意思就是让我们选出所有能组合为一个三角形的三个数的组合,并且如图两个二算两种。

1.2 思路解析

首先三角形成立的条件是两边之和大于第三边,两边之差小于第三边,但是如果我们按这个条件
来判断成立三角形的话可以倒是可以,但是太麻烦了,现在我们有一种新的思路:
假设:2 3 4是三角形三条边,那我们是不是可以只需要判断2+3>4即可,为什么呢?
因为2+4一定大于3,3+4一定大于2,3-2一定小于4、
当2+3>4成立时一定有4-3<2,4-2<3.

所以第一步我们需要将数组排序(这样更好找最大最小值)

在这里插入图片描述
然后我们固定第三条边和第一条边,我们通过改变第二条边来判断该组合是否成立:
这里有两种情况:
1、arr[o]+arr[t]>arr[tr],在这种情况下,arr[o]后面的所有值与arr[t]相加都大于arr[tr];
所以这种情况只需要计算区间的大小,区间的大小就是组合的数量

2、arr[o]+arr[t]<=arr[tr],这种情况下,无论我们如何移动左区间,和都小于arr[tr],所以我们现在要移动右区间,直到arr[o]+arr[t]>arr[tr];

大家下来可以画画图来理解一下.

总结:
在这里插入图片描述

1.3 代码实现

class Solution {
public:int triangleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());//算法库里的排序int tail=nums.size()-1;//最大边int count=0;//计数while(tail>=2)//第三条边必须要在第三个数组元素及以后{int left=0;//最小边int right=tail-1;while(left<right){if(nums[left]+nums[right]>nums[tail]){count+=right-left;right--;}else{left++;}}tail--;}return count;}
};

2、和为s的两个数

题目链接:
https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/

2.1 题目解析

在这里插入图片描述
这道题的意思就是需要我们在数组中找两个数,它们的和为target,只需要返回任意一组即可。

2.2 思路解析

这道题是不是类似于第一题啊,这一题我们的思路是:
在这里插入图片描述

假设这是我们的数组,我们还是需要先排序,然后计算arr[left]+arr[right]的和,在与target比较即可

三种情况:
‘<‘,这种情况我们直接left++即可
’>’,这种情况我们需要让right–;
‘==’,这组值就是我们需要的。

总结:
在这里插入图片描述

2.3 代码实现

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

3、三数之和

题目链接
https://leetcode.cn/problems/3sum/

3.1 题目解析

在这里插入图片描述
这道题难度就上来了,需要我们找出三个和为0的值,并且需要我们将相同组合给去掉(元素相同,顺序不同算同一组合)。

3.2 思路解析

解法一:暴力遍历,求出所有组合,通过容器set去重(太麻烦了)

解法二:双指针算法

现在这里的思路是先固定左边的一个数,这个数右边的部分作为一个区间,将左边这个数的相反数作为target,在右边的区间求两数之和等于target,这样我们的问题就变为求两数之和了。

在这里插入图片描述
重复上述操作,但是这道题难的部分是去重(去掉相同组合)。

去重需要注意的是这里由两部分需要去重:
第一部分是找到当前组合后left需要++,right需要- -,要是遇到相同元素需要跳过
第二部分是最左边的target遇到相同元素也需要去重

总结:
在这里插入图片描述

3.3 代码实现

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>>  vv;sort(nums.begin(),nums.end());int n=nums.size();for(int i=0;i<n;){int left=i+1,right=n-1,target=-nums[i];while(left<right){if(nums[left]+nums[right]<target) left++;else if(nums[left]+nums[right]>target) right--;else{vv.push_back({nums[left],nums[right],nums[i]});left++;right--;while(left<right&&nums[left]==nums[left-1]) left++;//遇到重复的while(left<right&&nums[right]==nums[right+1]) right--;//遇到重复的}}i++;while(i<n&&nums[i]==nums[i-1]) i++;//去重操作}return vv;}
};

4、四数之和

题目链接
https://leetcode.cn/problems/4sum/

4.1 题目解析

在这里插入图片描述
这道题与上面的三数求和十分类似,需要我们求四个数的和。

4.2 思路解析

上一题三数求和是在左边固定一个数,然后在右区间找两数,两数等于左边那个数的相反数,
这道题需要我们找四个数,那我们可以在左边固定两个数,然后右边的部分作为右区间,需要target-左边两个数=右边两数之和,完全类似,但是这道题需要注意的是int可能会溢出,我们需要使用long long,
其次三数求和是两个循环,需要注意两个地方的去重
而这里是三个循环,需要注意三个地方的去重:
1、left与right部分
2、左边两数中右边那数的去重
3、左边两数中最左边那个数的去重

总结
在这里插入图片描述

4.3 代码实现

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>>  vv;sort(nums.begin(),nums.end());int n=nums.size();for(int i=0;i<=n-4;){for(int j=i+1;j<=n-3;){int left=j+1,right=n-1;long long aim=(long long)target-nums[i]-nums[j];while(left<right){if(nums[left]+nums[right]<aim) left++;else if(nums[left]+nums[right]>aim) right--;else{vv.push_back({nums[i],nums[j],nums[left],nums[right]});left++,right--;while(left<right&&nums[left]==nums[left-1]) left++;while(left<right&&nums[right]==nums[right+1]) right--;}}j++;while(j<n&&nums[j-1]==nums[j]) j++;}i++;while(i<n&&nums[i-1]==nums[i]) i++;}return vv;}
};

5 总结

1、双指针常用于数组中元素的操作,但其他地方例如快乐数也可以使用,总的来说看到数组我们可以优先考虑双指针是否可行,然后考虑其他算法

2、在数组中对元素操作我们尽量都要画图,一定要考虑特殊情况,否则会把我们坑得死死的。


http://www.ppmy.cn/embedded/133964.html

相关文章

Mybatis使用和原理

Mybatis使用和原理 1、ORM架构2、Spring整合MyBatis使用2.1 添加maven依赖2.2 配置数据源2.3 创建实体类2.4 创建 MyBatis Mapper2.4.1 使用MyBatis注解2.4.2 使用XML方式 2.5 Service 层 3、Spring整合Hibernate使用3.1 添加maven依赖3.2 配置数据源3.3 创建实体类3.4 创建 Re…

好音质的百元头戴式耳机怎么选?四款高音质百元头戴式耳机推荐

选头戴式耳机的时候&#xff0c;品牌的选择常常让人犹豫不决。因为市面上的头戴式耳机品牌繁多&#xff0c;从知名的大牌到新兴的科技品牌&#xff0c;各种型号层出不穷&#xff0c;价格跨度也相当大。面对这些琳琅满目的选择&#xff0c;好音质的百元头戴式耳机怎么选&#xf…

爬虫+数据保存2

爬取数据保存到MySQL数据库 这篇文章, 我们来讲解如何将我们爬虫爬取到的数据, 进行保存, 而且是把数据保存到MySQL数据库的方式去保存。 目录 1.使用pymysql连接数据库并执行插入数据sql代码(insert) 2.优化pymysql数据库连接以及插入功能代码 3.爬取双色球网站的数据并保…

三种SPI机制的了解及使用

文章目录 1.SPI机制概念2.Java SPI2.1 创建一个项目&#xff0c;并创建如下模块2.2 db-api模块2.3 mysql-impl模块2.4 oracle-impl模块2.5 main-project模块 3.Spring SPI4.Dubbo SPI 1.SPI机制概念 SPI全程Service Provider Interface&#xff0c;是一种服务发现机制。 SPI的…

【网络】2.TCP通信

TCP通信 server1. 创建套接字2. 填充套接字3. 将套接字和监听文件描述符绑定4. 将_listensock设置为监听状态5. 启动服务器accept()函数read()函数 Server启动client1. 创建套接字2. 填充套接字connect()函数 3. 通过文件描述符向服务端发送信息 client启动 server server的启…

HTB:BoardLight[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are listening on BoardLight? 2.What is the domain name used by the box? 3.What is the name of the application running on a virtual host of board.htb? 4.What version of Dolibarr is running on Board…

群晖通过 Docker 安装 Firefox

1. 获取 firefox 镜像 在注册表搜索 jlesage/firefox&#xff0c;并且下载 2. 创建容器 运行映像 jlesage/firefox&#xff0c;开始创建容器 3. 配置容器 启用自动重新启动&#xff0c;重点配置存储空间和环境变量&#xff0c;其他默认。 创建文件夹&#xff0c;及子文件夹…

NavVis VLX三维激光扫描仪在市政地形测绘中的典型应用【沪敖3D】

项目&#xff1a;市政地形测绘 市政地形测绘涵盖了特定区域内的自然与人为特征&#xff0c;如道路、建筑物、桥梁等户外环境和结构。这一过程为各种工程、建筑、施工及土地开发项目提供了准确、全面的景观数据。 地形测绘常常是建设项目的首要步骤。因其普遍性&#xff0c;地…