【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字

【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字
在这里插入图片描述

【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字


双指针应用场景

应用场景介绍----------<----------链接直达请点击


目录

1. 有效三角形个数

1.1 题目链接

题目链接直达<----------请点击

1.2 题目描述

在这里插入图片描述

1.3 题目示例

在这里插入图片描述

1.4 算法思路

  1. 我们首先得清除构成三角形的条件:两边之和大于第三边,两边之差小于第三边,但是要验证这两个条件好像很麻烦,有没有更简单的方法呢?
  2. 当三个数a,b,c我们从小到大排序:然后你会发现只需要满足a + b > c就能构成一个有效的三角形。
  3. 在排序后的数组中,我们固定最大的边 nums[k] 作为三角形的第三边,然后在 [0, k-1] 范围内使用对撞指针寻找满足条件的两边。
  • 具体来说,设置 left = 0right = k-1。当 nums[left] + nums[right] > nums[k] 时,由于数组是升序排列,leftright-1 的所有位置与当前 right 组成的配对都能满足条件。这时我们可以直接给计数器增加 right - left 个有效组合,然后将 right 左移一位。
  • 如果 nums[left] + nums[right] <= nums[k],说明当前的两边之和太小,需要增大其中一边。由于 right 已经是当前范围内较大的值,我们通过将 left 右移来增加两边之和。

1.5 核心代码

#include<iostream>#include<vector>#include<algorithm>usingnamespace std;classSolution{public:inttriangleNumber(vector<int>& nums){sort(nums.begin(), nums.end());//升序排序int n = nums.size();//n为数组大小int ret =0;for(int i = n -1; i >=2; i--)//因为最少三条边,所以i>=2{int left =0, right = i -1;while(left < right){if(nums[left]+ nums[right]> nums[i]){ ret += right - left; right--;}else{ left++;}}}return ret;}};

1.6 示例测试(总代码)

#include<iostream>#include<vector>#include<algorithm>usingnamespace std;classSolution{public:inttriangleNumber(vector<int>& nums){sort(nums.begin(), nums.end());//升序排序int n = nums.size();//n为数组大小int ret =0;for(int i = n -1; i >=2; i--)//因为最少三条边,所以i>=2{int left =0, right = i -1;while(left < right){if(nums[left]+ nums[right]> nums[i]){ ret += right - left; right--;}else{ left++;}}}return ret;}};intmain(){ vector<int> nums1 ={4,2,3,4}; cout <<Solution().triangleNumber(nums1)<< endl;return0;}
在这里插入图片描述

2. 和为s的两个数字

2.1 题目链接

题目链接直达<----------请点击

2.2 题目描述

在这里插入图片描述

2.3 题目示例

在这里插入图片描述

2.4 算法思路

  1. 因为这个数组题目中已经说明是升序了,我们可以同样可以采用对撞指针来实现。
  2. 一个指向第一个数据,一个指向最后一个数据,然后让他们相加。如果结果大于traget说明过大,right–;如果结果小于traget说明太小,left++;如果相等就返回,直到left和right指向同一个位置循环停止。

2.5 核心代码

//有效三角形个数,和为s的两个数字#include<iostream>#include<vector>usingnamespace std;classSolution{public: vector<int>twoSum(vector<int>& price,int target){int left =0;int right = price.size()-1;while(left < right){if(price[left]+ price[right]> target){ right--;}elseif(price[left]+ price[right]< target){ left++;}else{return{ price[left],price[right]};//等价于vector<int> ans;//ans.push_back(price[left]);//ans.push_back(price[right]);//return ans;}}return{-1,-1};}};

2.6 示例测试(总代码)

//有效三角形个数,和为s的两个数字#include<iostream>#include<vector>#include<algorithm>usingnamespace std;classSolution{public: vector<int>twoSum(vector<int>& price,int target){int left =0;int right = price.size()-1;while(left < right){if(price[left]+ price[right]> target){ right--;}elseif(price[left]+ price[right]< target){ left++;}else{return{ price[left],price[right]};//等价于vector<int> ans;//ans.push_back(price[left]);//ans.push_back(price[right]);//return ans;}}return{-1,-1};}};intmain(){ vector<int> nums1 ={3,9,12,15}; vector<int> result =Solution().twoSum(nums1,18);// 正确输出vector的方式 cout <<"[";for(int i =0; i < result.size(); i++){ cout << result[i];if(i < result.size()-1){ cout <<",";}} cout <<"]"<< endl;return0;}
在这里插入图片描述

总结

在掌握了双指针基础模型(快慢指针、对撞指针)之后,我们进一步探索双指针在数学组合问题中的精妙应用。本篇通过「有效三角形个数」和「和为s的两个数字」两个经典问题。

掌握了这些基础模型后,我们可以进一步挑战:

🔢 三数之和 —— 在二维对撞基础上增加一维遍历,处理更复杂的组合约束
🔢 四数之和 —— 双层循环+对撞指针的组合应用,展现分治思想的威力
🎯 最接近的三数之和 —— 引入差值最小化的优化目标,拓展双指针的适用边界

这些进阶问题都建立在本文所述的核心思想之上——排序预处理 + 指针智能移动,体现了算法设计中"分而治之"的经典智慧。


下一篇,我们将深入探索多指针的高阶应用:
【C++】优选算法必修篇之双指针实战:三数之和 & 四数之和

Read more

【C++】STL有序关联容器的双生花:set/multiset 和 map/multimap 使用指南

【C++】STL有序关联容器的双生花:set/multiset 和 map/multimap 使用指南

🔥拾Ծ光:个人主页👨🏻‍💻 👏👏👏欢迎来到我的专栏: 🎉《C++》 📌《数据结构》 💡《C语言》 目录 前言: 1、set容器  常用接口说明: 1.1、构造函数——constructor 1.2、迭代器——iterator 1.3、插入——insert 1.4、删除——erase 1.5、查找——find 1.6、统计指定节点个数——count 1.7、区间查找——lower_bound/upper_bound 2、multiset容器  常用接口说明: 2.1、插入——insert 2.

By Ne0inhk
C++ 模板再升级:非类型参数、特化技巧(含全特化与偏特化)、分离编译破解

C++ 模板再升级:非类型参数、特化技巧(含全特化与偏特化)、分离编译破解

✨ 孤廖:个人主页 🎯 个人专栏:《C++:从代码到机器》 🎯 个人专栏:《Linux系统探幽:从入门到内核》 🎯 个人专栏:《算法磨剑:用C++思考的艺术》 折而不挠,中不为下 文章目录 * 前言 * 正文 * 1. 非类型模板参数 * 2. 模板的特化 * 2.1 概念 * 2.2 函数模板特化 * 2.3 类模板特化 * 2.3.1 全特化 * 2.3.2 偏特化 * 2.3.3 类模板特化应用示例 * 3 模板分离编译 * 3.1 什么是分离编译 * 3.2 模板的分离编译

By Ne0inhk
【C++】AVL 树平衡二叉搜索的神奇结构,代码实现全解析,从概念到应用,助你轻松掌握这一高效数据结构,编程能力更上一层楼!

【C++】AVL 树平衡二叉搜索的神奇结构,代码实现全解析,从概念到应用,助你轻松掌握这一高效数据结构,编程能力更上一层楼!

🌟个人主页:落叶  🌟当前专栏:C++专栏 目录 AVL树实现 AVL的概念 AVL树的实现 AVL树的结构 AVL树的插⼊ AVL树插⼊⼀个值的⼤概过程 平衡因⼦更新 插⼊结点及更新平衡因⼦的代码实现 旋转 旋转的原则 右单旋 右单旋代码实现 右单旋代码 左单旋  左单旋代码实现 左右双旋 左右双旋代码实现  左右双旋的代码  右左双旋 右左双旋代码实现  AVL树的查找  AVL树平衡检测 AVL树的代码  AVLtree.h test.cpp AVL树实现 AVL的概念 AVL树是最先发明的⾃平衡⼆叉查找树,AVL是⼀颗空树,或者具备下列性质的⼆叉搜索树:它的 左右⼦树都是AV树,

By Ne0inhk
【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

🔭 个人主页:散峰而望 《C语言:从基础到进阶》《编程工具的下载和使用》《C语言刷题》《算法竞赛从入门到获奖》《人工智能AI学习》《AI Agent》 愿为出海月,不做归山云 🎬博主简介 文章目录 * 前言 * 1. OJ(online judge)题目输入情况汇总 * 1.1 单组测试用例 * 1.2 多组测试用例 * 1.2.1 测试数据组数已知 * 1.2.2 测试数据组未知 * 1.2.3 特殊值结束测试数据 * 2. 输入时特殊技巧 * 2.1 含空格字符串的特殊处理方式 * 2.2 数字的特殊处理方式 * 3. scanf/printf 和

By Ne0inhk