PS:没事儿做做题,预防老年痴呆~

描述

给定一个未排序的整数数组,找到其中有给定总和的一对数字。
eg:
输入:

arr = [3,5,2,9,7,6,11,0]  
sum = 10

输出:
索引 0和4

只要找到一对数字即可。

方法一

最简单也是最暴力的方法,用两个循环遍历数组,判断两个数字之和,如果符合条件则返回数组下标。该方法比较简单,但是时间复杂度为O(n^2),比较高。

直接上代码,C++实现

// 时间复杂度O(n^2)  空间复杂度 O(1)
vector<int> findPair1(const vector<int> &arr,int sum)
{
for(int i = 0 ; i < arr.size()-1 ; ++i){

for(int j = i + 1 ; j < arr.size() ; ++j){
if(arr[i] + arr[j] == sum){
return {i,j};
}
}
}
return {};
}

int main()
{
vector<int> arr = {3,5,2,9,7,6,11,0};
int sum = 10;
auto ret = findPair1(arr,sum);
if(0 == ret.size()){
cout << "pair not found." << endl;
}
for(auto &iter : ret){
cout << iter << " ";
}
return 0;
}

方法二

第二种方法借用排序来实现,首先对数据进行排序,然后定义两个索引变量分别指向数组的头和尾,将索引头和尾的元素总和与期望值进行比较,如果小于期望值,则把低位索引加1,如果大于期望值,则把高位索引减1,通过循环直到低索引比高索引大,则返回。该方法时间复杂度为O(n*logn)。

上代码

// 时间复杂度O(nlogn)  空间复杂度 O(1)
vector<int> findPair2(vector<int> &arr,int sum)
{
std::sort(arr.begin(),arr.end());
int low = 0;
int high = arr.size() - 1;

while(low < high){

if(arr[low] + arr[high] == sum){
return {low,high};
}
(arr[low] + arr[high] > sum) ? high--:low++;
}
return {};
}

int main()
{
vector<int> arr = {3,5,2,9,7,6,11,0};
int sum = 10;
auto ret = findPair2(arr,sum);
if(0 == ret.size()){
cout << "pair not found." << endl;
}
for(auto &iter : ret){
cout << iter << " ";
}
return 0;
}

方法三

第三种方法,可以借用map来解决,将数组的元素值和索引对应存储在map中,通过检查 sum-arr[i] 是否存在于map来确定想要的值。刚方法效率最高,只需要通过一次循环即可完成,所以时间复杂度为O (n).

上代码:

// 时间复杂度O(n)  空间复杂度 O(n)
vector<int> findPair3(vector<int> &arr,int sum)
{
std::map<int,int> tempMap;
for(int i = 0 ; i < arr.size()-1 ; ++i){
if(tempMap.find(sum - arr[i]) != tempMap.end()){
return {tempMap[sum - arr[i]],i};
}
tempMap[arr[i]] = i;
}
return {};
}


int main()
{
vector<int> arr = {3,5,2,9,7,6,11,0};
int sum = 10;
auto ret = findPair3(arr,sum);
if(0 == ret.size()){
cout << "pair not found." << endl;
}
for(auto &iter : ret){
cout << iter << " ";
}
return 0;
}

该题比较简单,主要考虑在不同的情况下其时间和空间复杂度的区别。闲来无事,就当练练手吧,保持思维的运转,哈哈哈~