演算法題目
在一個包含n個整數的陣列S中,是否存在三個元素(a,b,c),使得a+b=c?如果存在,給出所有滿足a+b=c的(a,b,c)集合,不能重複。
注意:
- 三元素組合(a,b,c),要求(a,b)是升序的,即a<=b
- 結果集不能重複
例子:
陣列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;
}
}
複製程式碼