查找数组中和为某给定值的两个数
问题描述
给定一个数组arr,如{2, 6, 7, 4},以及一个数字target,如10。求数组中和为10的两个数。
分析
方法一:如果用暴力方法,时间复杂度是o(n2)。
代码
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers;
numbers.clear();
int a;
while (cin>>a && a!= -1)
{
numbers.push_back(a);
}
int target = numbers.at( numbers.size() - 1 );
numbers.resize( numbers.size() - 1 );
int index1=0;
for(vector<int>::iterator iter1 = numbers.begin(); iter1 != numbers.end() && flag; ++iter1, ++index1 )
{
int index2 = index1 + 1;
for(vector<int>::iterator iter2 = iter1 + 1; iter2 != numbers.end() && flag; ++iter2, ++index2)
{
cout<<index1<<" "<<index2<<endl;
if ( *iter1 == target -( *iter2) )
{
cout<<"index1= "<<index1<<" index2= "<<index2<<endl;
flag=0;
}
}
}
return 0;
}
方法二:利用C++11中的unordered_multimap,本题复杂度可降至o(n)。
unordered库提供两个散列集合类unordered_map和unordered_multimap,用法与STL里的标准关联容器map/multimap相同,只是内部使用散列表代替了二叉树实现,因此查找复杂度由对数降为常数。
代码:
#include <vector>
#include <iostream>
#include <unordered_map>
using namespace std;
vector<int> twosum( const vector<int> & numbers, int target )
{
unordered_multimap<int, int> hashmap;
vector<int> result;
for (int i=0; i<numbers.size(); i++)
hashmap.insert( {numbers.at(i), i+1} );
auto beg = hashmap.begin(); // Type: unordered_multimap<int, int>::iterator
for (; beg!=hashmap.end(); beg++)
{
auto get = hashmap.equal_range( target - beg->first ); // Type: pair<iterator,iterator>
auto resbeg = get.first; // Type: unordered_multimap<int, int>::iterator
auto resend = get.second; // Type: unordered_multimap<int, int>::iterator
result.push_back( beg->second < resbeg->second ? beg->second : resbeg->second );
result.push_back( beg->second > resbeg->second ? beg->second : resbeg->second );
return result;
}
return result;
}
int main()
{
int arr[] = {2, 6, 7, 4};
vector<int> input(arr, arr+4 );
auto res = twosum(input, 10); //Type: vector<int>
for(int i=0; i<res.size(); i++)
cout<<res.at(i)<<" ";
cout<<endl;
return 0;
}
对于c++11的初学者,本文提供了linux终端下编译和运行该代码的命令行:
g++ -std=gnu++0x twosum.cc -o twosum.out
./twosum.out