算法系列:三元组和


 

思路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向后移动。

 

[cpp] view plain copy
 
 print?
  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4.   
  5. void printPairSums(int data[], int size, int sum);  
  6. int main(int argc, char* argv[])  
  7. {  
  8.     int data[] = {1, 5, 9, -1, 4, 6, -2, 3, -8};  
  9.     int size = sizeof(data) / sizeof(data[0]);  
  10.     int i;  
  11.     sort(data, data + size);  
  12.     printPairSums(data, size, 8);  
  13.   
  14.     return 0;  
  15. }  
  16. void printPairSums(int data[], int size, int sum)  
  17. {  
  18.     int first = 0;  
  19.     int last = size -1;  
  20.     int s = 0;  
  21.     while (first < last)  
  22.     {  
  23.         s = data[first] + data[last];  
  24.         if (s == sum)  
  25.         {  
  26.             cout << data[first] << " + " << data[last] << " = " << sum << endl;  
  27.             first++;  
  28.             last--;  
  29.         }  
  30.         else if (s < sum)  
  31.         {  
  32.             first++;  
  33.         }  
  34.         else  
  35.         {  
  36.             last--;  
  37.         }  
  38.     }  
  39. }  


 

思路:  对于二元组的和等于给定值的情况,可以参考http://blog.csdn.net/lalor/article/details/7554594, 即将数组排序后,用两个指向数组的指针,一个从前向后扫描,一个从后向前扫描,记为first和last,当first + last == sum 则找到了一对二元组,它们的和等于sum,如果first + last < sum 则 first++, first + last > sum 则last--。同样,三元组的情况,先将数组排序,然后固定一个元素,再去寻找一个二元组的和为sum - val,这样就将三元组的问题,转换成了二元组的问题。


程序如下:

 

[cpp] view plain copy
 
 print?
  1. #include <iostream>  
  2. #include <algorithm>  
  3.   
  4. using namespace std;  
  5.   
  6. bool find3Numbers(int A[], int arr_size, int sum)  
  7. {  
  8.     int l, r;  
  9.     /* Sort the elements */  
  10.     sort(A, A + arr_size);  
  11.   
  12.     /* Now fix the first element one by one and find the  
  13.      * other two elements 
  14.      */  
  15.     for (int i = 0; i < arr_size - 2; i++)   
  16.     {  
  17.         // to find the other two elements, start two index variables  
  18.         //from two corners of the array and move toward each other  
  19.   
  20.         l = i + 1; //index of the first element in the remaining elements  
  21.         r = arr_size - 1;//index of the last element  
  22.   
  23.         while (l < r)   
  24.         {  
  25.             if (A[i] + A[l] + A[r] == sum)   
  26.             {  
  27.                 cout << "Triplet is\t" << A[i] << "\t" << A[l] << "\t" << A[r] << endl;  
  28.                 return true;  
  29.             }  
  30.             else if (A[i] + A[l] + A[r] < sum)   
  31.             {  
  32.                 l++;  
  33.             }  
  34.             else // A[i] + A[l] + A[r] > sum  
  35.             {  
  36.                 r--;  
  37.             }  
  38.               
  39.         }  
  40.     }  
  41.     // If we reach here, then no triplet was found  
  42.     return false;  
  43. }  
  44.   
  45. /* Driver program to test above function */  
  46. int main(int argc, char* argv[])  
  47. {  
  48.     int A[] = {1, 4, 45, 6, 10, 8};  
  49.     int sum = 22;  
  50.     int arr_size = sizeof(A) / sizeof(A[0]);  
  51.   
  52.     find3Numbers(A, arr_size, sum);  
  53.     return 0;  
  54. }  


方法2(回溯法),也能得到不错的效率

 

 

[cpp] view plain copy
 
 print?
  1. #include <iostream>  
  2. #include <algorithm>  
  3.   
  4. using namespace std;  
  5.   
  6. const int S = 22;  
  7.   
  8. int sumCheck(int A[], int start, int end, int arr[], int cnt)  
  9. {  
  10.     if (cnt == 2)   
  11.     {  
  12.         int sum = arr[0] + arr[1] + arr[2];  
  13.         if (sum == S)   
  14.         {  
  15.             cout << arr[0] << "\t" << arr[1] << "\t" << arr[2] << endl;  
  16.         }  
  17.         return 0;  
  18.     }  
  19.   
  20.     if (start > end || cnt > 2)   
  21.     {  
  22.         return -1;  
  23.     }  
  24.   
  25.     int i = start;  
  26.   
  27.       
  28.     arr[++cnt] = A[i];  
  29.     sumCheck(A, start + 1, end, arr, cnt);  
  30.     arr[cnt] = 0;  
  31.     cnt--;  
  32.     sumCheck(A, start + 1, end, arr, cnt);  
  33. }  
  34.   
  35. /* Driver program to test above function */  
  36. int main(int argc, char* argv[])  
  37. {  
  38.     int A[] = {1, 4, 45, 6, 10, 8};  
  39.     int arr_size = sizeof(A) / sizeof(A[0]);  
  40.     int cnt = -1;  
  41.     int arr[3] = {0, 0, 0};  
  42.   
  43.     sumCheck(A,0, arr_size-1, arr, cnt);  
  44.     return 0;  
  45. }  

 

posted @ 2016-07-12 22:10  朔方  阅读(954)  评论(0编辑  收藏  举报