【优选算法必刷100题】第007~008题(双指针算法):三数之和、四数之和问题求解

【优选算法必刷100题】第007~008题(双指针算法):三数之和、四数之和问题求解

🔥艾莉丝努力练剑:个人主页

专栏传送门:《C语言》《数据结构与算法》C/C++干货分享&学习过程记录Linux操作系统编程详解笔试/面试常见算法:从基础到进阶

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬艾莉丝的算法专栏简介:



目录

007  三数之和

1.1  题目解析

1.2  思路1:暴力

1.3  思路2:排序 + 双指针

1.3.1  算法思路

1.3.2  代码实现

1.4  过程推算

1.5  反思

008  四数之和

2.1  题目解析

2.2  思路1:暴力

2.3  思路2:排序 + 双指针

2.3.1  算法思路

2.3.2  代码实现

2.4  过程推算

2.5  反思

结尾


007  三数之和

力扣链接:15. 三数之和

力扣题解链接:排序+双指针解决【三数之和】

题目描述:

1.1  题目解析

1.2  思路1:暴力

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

时间复杂度:O(n^3),空间复杂度:O(logn)。

1.3  思路2:排序 + 双指针

1.3.1  算法思路

本题与两数之和类似,是非常经典的面试题。与两数之和稍微不同的是,题目中要求找到所有【不重复】的三元组。那我们可以利用在两数之和那里用的双指针思想,来对我们的暴力枚举做优化:

1、先排序;

2、然后固定一个数a:

3、在这个数后面的区间内,使用「双指针算法」快速找到两个数之和等于a即可。

但是要注意的是,这道题里面需要有【去重】操作——

1、找到一个结果之后,left和[right指针要【跳过重复】的元素;

2、当使用完一次双指针算法之后,固定的a也要【跳过重复】的元素。

1.3.2  代码实现

代码演示:

class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> ret; //1、排序 sort(nums.begin(),nums.end()); //2、固定 int n = nums.size(); for(int i = 0;i < n;) { int left = i + 1,right = n - 1,target = -(nums[i]); while(left < right) { //a <= 0 if(nums[i] > 0)break; int sum = nums[left] + nums[right]; if(sum > target)right--; else if(sum < target)left++; else{ ret.push_back({nums[i],nums[left],nums[right]}); left++; right--; //继续缩小区间 //left、right查重 while(left < right && nums[left] == nums[left - 1])left++; while(left < right && nums[right] == nums[right + 1])right--; } } //i查重 //i在这里移动,不在for循环 i++; while(i < n && nums[i] == nums[i - 1])i++; } return ret; } };
时间复杂度:O(n^3),空间复杂度:O(logn)。

1.4  过程推算

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下!

1.5  反思

总结:

1、没学到STL,vector<vector<int>> ret;和ret.push_back({nums[i],nums[left],nums[right]});这步根本想不到,直接来刷题了,对自己的实力没有清晰的认知(QAQ);

2、没想到固定的值a <= 0,这个常数级别的小优化想不到;

3、还是去重操作,都在一个条件判断下去重了,left和right在while(left < right)里面去重,i应该在它外面去重,因为刚才我已经让for循环的i++(i移动)这个操作搬到for里面来进行了,这样去重了,这样移动完之后,得到的i就是下一步我要固定的那个数了;

4、i移动的操作在while循环里面搞定,for循环for(int i = 0;i < n;)这个可以空着不写没有想到;

5、时间复杂度:O(n^2),for循环嵌套一个while循环;

6、空间复杂度:无限接近于O(logn)——只是在排序那里稍微占了点空间,压栈会占用logn的空间,其他都是只用了有限个变量。

008  四数之和

力扣链接:18. 四数之和

力扣题解链接:排序+双指针解决【四数之和】问题

题目描述:

2.1  题目解析

如下所示——

2.2  思路1:暴力

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

大家直接去看上面的【三数之和】:

2.3  思路2:排序 + 双指针

2.3.1  算法思路

1、依次固定一个数a;
2、在这个数a的后面区间上,利用【三数之和】找到三个数,使这三个数的和等于target - a即可,这里注意有两个区间,大的区间里面固定一个数b,小的区间里面定义一个left和right两个下标指针,里面的两数之和,加上a和b,加起来和target比。

2.3.2  代码实现

代码演示——

class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { // 创建数组,存放返回值 vector<vector<int>> ret; // 1、排序 sort(nums.begin(), nums.end()); // 2、固定i int n = nums.size(); for (int i = 0; i < n;) { // 固定j for (int j = i + 1; j < n;) { // 3、双指针 int left = j + 1, right = n - 1; while (left < right) { // // a >= 0 // if (nums[i] > 0) // break; // // b >= 0 // if (nums[j] > 0) // break; long sum = nums[left] + nums[right]; long tmp = nums[i] + nums[j]; if (sum > (target - tmp)) right--; else if (sum < (target - tmp)) left++; else { ret.push_back( {nums[i], nums[j], nums[left], nums[right]}); left++; right--; // left、right去重 while (left < right && nums[left] == nums[left - 1]) left++; while (left < right && nums[right] == nums[right + 1]) right--; } } // j查重,j移动 j++; while (j < n && nums[j] == nums[j - 1]) j++; } // i查重,i移动 i++; while (i < n && nums[i] == nums[i - 1]) i++; } return ret; } };
时间复杂度:O(n^3),空间复杂度:O(logn)。

2.4  过程推算

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下!

2.5  反思

1、整体做下来思路正确、逻辑没问题,这一点值得肯定(这里出的岔子就是在a <= 0,b <= 0的判断加上,就报错了);
2、没有自己独立地想到int类型遇到超级大的数据会怎么样,这里要在定义变量的时候把类型改成long,或者直接临时强制类型转换;
3、吸取了vector<vrctor<int>> ret;和ret.push_back({...});的教训,可以的!

结尾

往期回顾:

【优选算法必刷100题】第005~006题(双指针算法):有效三角形的个数、查找总价格为目标值的两个商品问题求解

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡

૮₍ ˶ ˊ ᴥ ˋ˶₎ა


Read more

【AI】高效交互的艺术:AI提示工程与大模型对话指南

【AI】高效交互的艺术:AI提示工程与大模型对话指南

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《AI》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、ChatatGPT介绍 * 二、什么是提示工程? * 三、大语言模型的底层原理 * 四、AI的相关术语 * 五、如何与AI(以ChatatGPT为例)更好交流 * 5.1 使用AI的核心 * 5.2 提示组成结构 * 5.3 创建好的提示的策略 * 5.4 提示的类别 * 5.5 创建在和AI提示的进阶框架 * 5.6如何减少AI回答的空洞无味感 * 5.7 如何提高AI回答的可读性 * 六、使用AI的更多技巧 * 6.1 高效提示的原则 * 6.

By Ne0inhk

人工智能与机器学习在软件工程中的应用:探索AL和ML技术如何改变软件的开发方式

作为一名正在深入学习软件工程的学生,近期我在完成课程项目时,对“人工智能与机器学习如何改变软件开发”这一主题进行了初步探索。随着调研的深入,我愈发意识到,AI与机器学习不再仅仅是软件所实现的功能特性,它们正在从根本上改变软件的生产方式。在此,我将自己的学习笔记与思考整理成文,希望能与社区的前辈和同学们交流探讨。鉴于本人学识尚浅,文中如有不当之处,恳请各位批评指正。 一、集成开发环境的智能化与软件质量保障的变革 传统的手工编码方式正在被AI赋能的新型开发工具所补充甚至取代,其中最为显著的便是集成开发环境的智能化转型。以GitHub Copilot、Amazon CodeWhisperer为代表的AI编程助手,已超越了传统的语法补全功能,它们能够基于上下文理解开发者的意图,实现从函数体自动补全到基于自然语言注释的代码生成,这种能力催生了“意图驱动开发”的雏形,开发者越来越多地将精力从语法细节转移到逻辑审查与架构设计上,人与机器的协作关系正在被重新定义。与此同时,在软件质量保障领域,机器学习技术的引入使得测试与缺陷预测变得更加精准和具有前瞻性,机器学习模型能够分析代码路径和执行逻辑,自

By Ne0inhk
AI 进化论:从 Function Calling 到 MCP

AI 进化论:从 Function Calling 到 MCP

AI 进化论:从 Function Calling 到 MCP,你的大模型还在“裸奔”吗? 文章目录 * AI 进化论:从 Function Calling 到 MCP,你的大模型还在“裸奔”吗? * 一、 给 AI 装上手脚:Function Calling 到底是个啥? * 1. 专业解释与大白话解读 * 2. 核心功能与代码示例 * 二、 实战演练:搭建你的“门票数据助手” * 1. 业务场景介绍 * 2. 进阶:一次调用,搞定查询 + 可视化 * 三、 MCP:AI 界的“USB-C”接口协议来了! * 1.

By Ne0inhk
清华团队首发OpenClaw研究报告:AI智能体生态闭环全解析

清华团队首发OpenClaw研究报告:AI智能体生态闭环全解析

🍃 予枫:个人主页 📚 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》《Java 面试刷题指南》 💻 Debug 这个世界,Return 更好的自己! 引言 近期“龙虾”OpenClaw持续爆火,GitHub星标数一路飙升,成为AI智能体领域的现象级开源项目。就在这时,清华沈阳教授团队重磅首发两份OpenClaw专项研究报告,从理论到实践、从自我研究到生态布局,给出了最全面的解读,堪称OpenClaw学习的“官方指南”,程序员和AI从业者必看! 文章目录 * 引言 * 一、OPENCLAW双报告核心概况 * 1.1 《OpenClaw发展研究报告1.0》:严谨迭代的生态指南 * 1.2 《OpenClaw自我研究报告1.0》:AI研究AI的标杆实验 * 二、OPENCLAW领域阶段性进展 * 2.1 理论研究:筑牢生态基础,扩大科普影响力 * 2.2 模型研发:

By Ne0inhk