算法学习之一:3SUM变体

博客围绕面试遇到的算法题展开,题目是在含n个整数的数组S中找满足a+b=c的(a,b,c)集合且不重复。解题思路是先将数组降序排序,时间复杂度O(nlogn),再遍历数组确定c,转化为2SUM问题,时间复杂度O(n^2),总复杂度为O(n^2)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法题目

在一个包含n个整数的数组S中,是否存在三个元素(a,b,c),使得a+b=c?如果存在,给出所有满足a+b=c的(a,b,c)集合,不能重复。

注意:

  1. 三元素组合(a,b,c),要求(a,b)是升序的,即a<=b
  2. 结果集不能重复

例子:

数组S = {1, 1, 2, -1, -4},

结果集为:
{-1, 2, 1}
{1, 1, 2}
复制代码

思路

这是我面试一个动漫公司遇到的题,是经典3SUM问题的一种变体,整体思路跟3SUM一样,但略作改变。

第一步,排序,排成降序的,如果S = {1, 1, 2, -1, -4},则排序后为 {2, 1, 1, -1, -4},这一步的时间复杂度为O(nlogn);

第二步,遍历排序后的数组,并取遍历得到的值为c。确定了c以后,接下来问题就变成了,在排序后的数组中寻找两个元素之和等于某个数,这是经典的2SUM问题,时间复杂度为O(n)。总共有n次遍历,每一次的时间复杂度为O(n),因此这一步的时间复杂度为 O(n^2)。

两步总的时间复杂度为O(nlogn) + O(n^2) = O(n^2)。

亮点

我在学习过程中,特别惊艳于,能在O(n)的时间复杂度内,从有序数组中寻找两个元素之和等于某个数。

具体的思路如下:

还是十分巧妙的。

代码

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

bool AscendingCompare(int i,int j) { 
    return i > j;
}

class Solution {
public:
	vector<vector<int>> FindSumEqual(vector<int>& array) {
		sort(array.begin(), array.end(), AscendingCompare);
    
		set<vector<int>> results;
		for (int i = 0; i < array.size(); i++) {
			int j = 0;
			int k = array.size() - 1;
			while (j < k) {
				if (array[j] + array[k] == array[i]) {
					results.insert({array[k], array[j], array[i]});
					j++;
					k--;
					while (j < k && array[j] == array[j + 1]) {
						j++;
					}
					while (j < k &&  array[k] == array[k - 1]) {
						k--;
					}
				} else if (array[j] + array[k] > array[i]) {
					j++;
				} else {
					k--;
				}
			}
		}
		vector<vector<int>> results_vector(results.begin(), results.end());

		return results_vector;
	}
}
复制代码

转载于:https://juejin.im/post/5b855b4be51d4538a515ba5f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值