思路1:可以用hash表来存储数组中的元素,这样我们取得一个数后,去判断sum - val 在不在数组中,如果在数组中,则找到了一对二元组,它们的和为sum,该算法的缺点就是需要用到一个hash表,增加了空间复杂度。
思路2:同样是基于查找,我们可以先将数组排序,然后依次取一个数后,在数组中用二分查找,查找sum -val是否存在,如果存在,则找到了一对二元组,它们的和为sum,该方法与上面的方法相比,虽然不用实现一个hash表,也没不需要过多的空间,但是时间多了很多。排序需要O(nLogn),二分查找需要(Logn),查找n次,所以时间复杂度为O(nLogn)。
思路3:该方法基于第2种思路,但是进行了优化,在时间复杂度和空间复杂度是一种折中,但是算法的简单直观、易于理解。首先将数组排序,然后用两个指向数组的指针,一个从前往后扫描,一个从后往前扫描,记为first和last,如果 fist + last < sum 则将fist向前移动,如果fist + last > sum,则last向后移动。
-
#include <iostream>
-
#include <algorithm>
-
using namespace std;
-
-
void printPairSums(int data[], int size, int sum);
-
int main(int argc, char* argv[])
-
{
-
int data[] = {1, 5, 9, -1, 4, 6, -2, 3, -8};
-
int size = sizeof(data) / sizeof(data[0]);
-
int i;
-
sort(data, data + size);
-
printPairSums(data, size, 8);
-
-
return 0;
-
}
-
void printPairSums(int data[], int size, int sum)
-
{
-
int first = 0;
-
int last = size -1;
-
int s = 0;
-
while (first < last)
-
{
-
s = data[first] + data[last];
-
if (s == sum)
-
{
-
cout << data[first] << " + " << data[last] << " = " << sum << endl;
-
first++;
-
last--;
-
}
-
else if (s < sum)
-
{
-
first++;
-
}
-
else
-
{
-
last--;
-
}
-
}
-
}
思路: 对于二元组的和等于给定值的情况,可以参考http://blog.csdn.net/lalor/article/details/7554594, 即将数组排序后,用两个指向数组的指针,一个从前向后扫描,一个从后向前扫描,记为first和last,当first
+ last == sum 则找到了一对二元组,它们的和等于sum,如果first + last < sum 则 first++, first + last > sum 则last--。同样,三元组的情况,先将数组排序,然后固定一个元素,再去寻找一个二元组的和为sum - val,这样就将三元组的问题,转换成了二元组的问题。
程序如下:
-
#include <iostream>
-
#include <algorithm>
-
-
using namespace std;
-
-
bool find3Numbers(int A[], int arr_size, int sum)
-
{
-
int l, r;
-
-
sort(A, A + arr_size);
-
-
-
-
-
for (int i = 0; i < arr_size - 2; i++)
-
{
-
-
-
-
l = i + 1;
-
r = arr_size - 1;
-
-
while (l < r)
-
{
-
if (A[i] + A[l] + A[r] == sum)
-
{
-
cout << "Triplet is " << A[i] << " " << A[l] << " " << A[r] << endl;
-
return true;
-
}
-
else if (A[i] + A[l] + A[r] < sum)
-
{
-
l++;
-
}
-
else
-
{
-
r--;
-
}
-
-
}
-
}
-
-
return false;
-
}
-
-
-
int main(int argc, char* argv[])
-
{
-
int A[] = {1, 4, 45, 6, 10, 8};
-
int sum = 22;
-
int arr_size = sizeof(A) / sizeof(A[0]);
-
-
find3Numbers(A, arr_size, sum);
-
return 0;
-
}
方法2(回溯法),也能得到不错的效率
-
#include <iostream>
-
#include <algorithm>
-
-
using namespace std;
-
-
const int S = 22;
-
-
int sumCheck(int A[], int start, int end, int arr[], int cnt)
-
{
-
if (cnt == 2)
-
{
-
int sum = arr[0] + arr[1] + arr[2];
-
if (sum == S)
-
{
-
cout << arr[0] << " " << arr[1] << " " << arr[2] << endl;
-
}
-
return 0;
-
}
-
-
if (start > end || cnt > 2)
-
{
-
return -1;
-
}
-
-
int i = start;
-
-
-
arr[++cnt] = A[i];
-
sumCheck(A, start + 1, end, arr, cnt);
-
arr[cnt] = 0;
-
cnt--;
-
sumCheck(A, start + 1, end, arr, cnt);
-
}
-
-
-
int main(int argc, char* argv[])
-
{
-
int A[] = {1, 4, 45, 6, 10, 8};
-
int arr_size = sizeof(A) / sizeof(A[0]);
-
int cnt = -1;
-
int arr[3] = {0, 0, 0};
-
-
sumCheck(A,0, arr_size-1, arr, cnt);
-
return 0;
-
}