当前位置: 首页 > news >正文

leetcode 15 三数之和

1. 题意

在数组中找到 和为指定值的三元组。

2. 题解

  • 排序 + 双指针

这个题目最关键的有两点:

一是利用排序和与前一个元素比较来去重;

二是通过数量关系写出双指针的解法。

2.1 暴力

三重循环枚举三元组,时间复杂度O(n3)O(n^3)O(n3)

当然会有重复的,我们排序后,那些相同的三元组肯定会排在一块的。

因此可以通过与前一个元素比较来去重。

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort( nums.begin(), nums.end());vector<vector<int>> ans;int n = nums.size();for (int i = 0;i < n - 2; ++i) {for (int j = i + 1; j < n - 1; ++j) {for (int k = j + 1; k < n; ++k) {if ( nums[i] + nums[k] + nums[j] == 0) {ans.push_back({ nums[i], nums[j], nums[k]});}}}}auto cmp = [](const vector<int> &a, const vector<int> &b) {if ( a[0] != b[0] )return a[0] < b[0];if ( a[1] != b[1] )return a[1] < b[1];return a[2] < b[2];};sort(ans.begin(), ans.end(), cmp );if (ans.size() > 1) {for (auto it = ans.begin() + 1; it != ans.end(); ) {if ( *it == *(it - 1)) {it = ans.erase(it);}else {++it;}}}return ans;}
};

实际上我们可以一开始就把数组给排序,从而避免重复三元组的枚举来达到去重的目的。

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort( nums.begin(), nums.end());vector<vector<int>> ans;int n = nums.size();for (int i = 0;i < n - 2;++i) {if ( i && nums[i] == nums[i-1])continue;for (int j = i + 1; j < n - 1; ++j) {if ( j > i + 1 && nums[j] == nums[j-1]) continue;for (int  k = j + 1; k < n; ++k) {if ( k > j + 1 && nums[k] == nums[k - 1])continue;int v = nums[i] + nums[j] + nums[k];if (0 == v) {ans.push_back( {nums[i], nums[j], nums[k]});}}}}return ans;}
};
2.2 二分

我们可以在枚举三元组的基础上,只需要枚举二元组iji\ ji j

并在区间[j+1,n)[j+1,n)[j+1,n)中查找−(nums[i]+nums[j])-(nums[i]+nums[j])(nums[i]+nums[j])

这样时间复杂度就降为了O(n2log⁡2n)O(n^2\log_2 n)O(n2log2n)

同样我们还是需要去重滴。

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort( nums.begin(), nums.end());vector<vector<int>> ans;int n = nums.size();for (int i = 0;i < n - 2;++i) {if ( i && nums[i] == nums[i-1])continue;for (int j = i + 1; j < n - 1; ++j) {if ( j > i + 1 && nums[j] == nums[j-1]) continue;int sv = -( nums[i] + nums[j] );auto it  = lower_bound( nums.begin() + j + 1, nums.end(), sv );if ( it != nums.end() && *it == sv ) {ans.push_back({nums[i], nums[j], sv});}}}return ans;}
};
2.3 相向双指针

双指针的做法主要利用有序性,把j,kj,kjk的枚举给关联起来了。

对于三重循环的枚举,j,kj,kj,k实际上相当于同向双指针的枚举。

我们根据a+b+c=a+b′+c′,b<b′a+b+c=a+b'+c',b<b'a+b+c=a+b+cb<b,必然可以得出c′<cc' < cc<c

由于我们的数组是排好序的,因此必然有

idx(b)<idx(b′)<idx(c′)<idx(c)idx(b) < idx(b') <idx(c')<idx(c)idx(b)<idx(b)<idx(c)<idx(c)

也就是在排序好的数组中,这四个数的位置依次是bb′c′cb\ b'\ c'\ cb b c c

因此我们一开始的时候,可以把kkk位置放到最后进行枚举

j=i+1,k=n−1j=i+1,k=n-1 j=i+1,k=n1

由于iii位置固定,实际子问题变成了在[j,k][j,k][j,k]中查找和为−nums[i]-nums[i]nums[i]

有序对。而这个问题其实就是两数之和 II。

更进一步的解释就不写了,可以参考两数之和II的题解。

时间复杂度O(n2)O(n^2)O(n2)

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort( nums.begin(), nums.end());vector<vector<int>> ans;int n = nums.size();for (int i = 0;i < n - 2;++i) {if ( i && nums[i] == nums[i-1])continue;int j = i + 1;int k = n - 1;while ( j < k) {int lsum = -(nums[i] + nums[j]);if ( nums[k] > lsum)k--;else if ( lsum == nums[k] ) {ans.push_back( { nums[i], nums[j], nums[k]});j++;while (j < k && nums[j - 1] == nums[j])j++;}   else {j++;}}}return ans;}
};

3. 参考

leetcode
0x3f

http://www.dtcms.com/a/325819.html

相关文章:

  • 【《数字货币量化交易:Linux下策略回测平台的搭建》】
  • 2025-2026 专升本论文写作【八项规范】
  • [202404-B]画矩形
  • 微信小程序常用 API
  • Arcpy-重采样记录
  • B站直播, 拼接4个窗口,能否实现
  • 从源码看 Coze:Agent 的三大支柱是如何构建的?
  • 【优化】图片批量合并为word
  • 嵌入式学习day24
  • MySQL的索引(索引的数据结构-B+树索引):
  • P2865 [USACO06NOV] Roadblocks G
  • 音视频学习(五十三):音频重采样
  • 数据备份与进程管理
  • AI大模型:(二)5.1 文生视频(Text-to-Video)模型发展史
  • Apache ECharts 6 核心技术解密 – Vue3企业级可视化实战指南
  • Apache Ignite 核心组件:GridClosureProcessor解析
  • ChatML vs Harmony:深度解析OpenAI全新对话结构格式的变化
  • 基于Spring Boot房源信息推荐系统的设计与实现 -项目分享
  • Maven <pom.xml> 标签详尽教程
  • perl notes【1】
  • 云原生环境Prometheus企业级监控
  • 【Node.js从 0 到 1:入门实战与项目驱动】1.3 Node.js 的应用场景(附案例与代码实现)
  • 论文阅读:Aircraft Trajectory Prediction Model Based on Improved GRU Structure
  • 《开源标准推动Linux驱动生态繁荣》
  • 实现分页功能【jQuery】
  • GDB调试 core dump 文件与栈溢出分析
  • 《Python入门:从零到Hello World的极简指南》
  • 板子 7.20--8.11
  • Spring Boot 参数校验 Validation 入门
  • 华为云计算的行业趋势:迈向智能、融合与绿色的未来