我试图在数组中找到总和等于k的所有对,解决方案需要O(n * log(n))时间。这是代码段 -
map<int,int> mymap;
map<int,int>::iterator it;
cin>>n>>k;
for( int i = 0 ; i < n ; i++ ){
cin>>a;
if( mymap.find(a) != mymap.end() )
mymap[a]++;
else
mymap[a] = 1;
}
for( it = mymap.begin() ; it != mymap.end() ; it++ ){
int val = it->first;
if( mymap.find(k-val) != mymap.end() ){
cnt += min( it->second, mymap.find(k-val)->second );
it->second = 0;
}
}
cout<<cnt;
我发现很难找到总和大于或等于k的所有对。我能想到的只是一个O(n ^ 2)解决方案。 O(n ^ 2)可以是通过遍历数组找到所有对的强力方法。 任何人都可以帮助我找到更好的解决方案,O(n)或O(nlgn)可能(如果存在)
答案 0 :(得分:6)
另一种方法是在最好的情况下采用O(log n),在最坏的情况下使用O(nlog n)来获得正数:
例如我们有数组{1,3,5,8,11}和k = 10,所以在第一步我们将得到k / 2 = 5和对{5,7},{8,11} ,{8,11}。这些对的计数将通过公式1 *(1-1)/ 2计算,其中l =元素的数量> = k / 2。在我们的情况下,l = 3,所以count = 3 * 2/2 = 3。
在3号的第二步,镜像元素将是7(5-2 = 3和5 + 2 = 7),因此对{3,8}和{3,11}将感兴趣。对于1个数字镜子将是9(5-4 = 1和5 + 4 = 9),因此{1,11}是我们寻找的。 p>
因此,如果k / 2 <第一个数组元素,这个算法将是O(log n)。
对于否定,算法会稍微复杂一点,但也可以用相同的复杂度来解决。
答案 1 :(得分:5)
使用所谓的&#34;两个指针&#34>存在一种相当简单的O(n)
方法。或者&#34;两个迭代器&#34;做法。关键的想法是在同一个数组上运行两个迭代器(不一定是C ++迭代器,索引也会这样做),这样如果第一个迭代器指向值x
,那么第二个迭代器点到数组中的最小元素小于k-x
。
我们将增加第一个迭代器,在执行此操作时,我们还将更改第二个迭代器以维护此属性。注意,随着第一个指针的增加,第二个指针的相应位置只会减小,所以在每次迭代时我们都可以从我们在前一个迭代处停止的位置开始;我们永远不需要增加第二个指针。这就是我们实现O(n)
时间的方式。
代码是这样的(没有测试这个,但想法应该清楚)
vector<int> a; // the given array
int r = a.size() - 1;
for (int l=0; l<a.size(); l++) {
while ((r >= 0) && (a[r] >= k - a[l]))
r--;
// now r is the maximal position in a so that a[r] < k - a[l]
// so all elements right to r form a needed pair with a[l]
ans += a.size() - r - 1; // this is how many pairs we have starting at l
}
另一种可能更简单的编码方法,但有点慢,是O(n log n)
使用二进制搜索。对于数组的每个元素a[l]
,您可以找到最大位置r
,以便a[r]<k-a[l]
使用二分搜索(这与第一个算法中的r
相同)。
答案 2 :(得分:0)
@Drew Dormann - 谢谢你的评论。
用两个指针运行数组。 left
和right
。
假设left
偏小,请从位置left
的{{1}}开始,然后0
向左移动,直至right
为止。
达到此目的后,a[left]+a[right] >= k
然后,您将total_count += (a.size - right + 1)
向前移动一步,left
需要(可能)向它移动。重复这个直到他们见面。
完成后,让我们说他们在地点right
会面,然后x
。
答案 3 :(得分:0)
步骤2也需要O(n log n)。 for循环运行n次。在循环内,我们对每个节点执行二进制搜索,即log n步骤。因此,算法的总体复杂度为O(n log n)。
答案 4 :(得分:-2)
这应该做的工作:
void count(int A[], int n) //n being the number of terms in array
{ int i, j, k, count = 0;
cin>>k;
for(i = 0; i<n; i++)
for(j = 0; j<n; j++)
if(A[i] + A[j] >= k)
count++ ;
cout<<"There are "<<count<<" such numbers" ;
}