【问题标题】:Find the indices of pairs whose sum is x找到总和为 x 的对的索引
【发布时间】:2014-02-08 21:39:50
【问题描述】:

给定一个数组,我必须找到总和等于 x 的对的索引。

假设数组是arr[5] = 1 2 3 4 2 和 sum = 5,那么对是 (1,4)、(2,3) 和 (3,2)。

我需要存储用于

的对的索引
(1,4) => (0,3)
(2,3) => (1,2)
(3,2) => (2,4)

所以答案是:(0,3),(1,2),(2,4)

我正在使用哈希映射。这是我的功能:

pair<int,int> index[5];
int FindPairs(int arr[],int n, int sum) {
    int i, temp,count=0,seta[n],setb[n],j;
bool hash[MAX] = {0}; 
for(i = 0; i < n; ++i)  {
    temp = sum - arr[i];
    if(temp >= 0 && hash[temp]  == 1 ) 
           seta[count++] = i;
    hash[arr[i]] = 1;
}
if(count == 0) return 0;
for(i=0;i<count;++i){
    for(j=0;j<n;j++){
        if( (sum - arr[seta[i]]) ==arr[j]  ) {
            setb[i] = j;
            break;
        }
    }
}
for(i=0;i<count;++i)  index[i] = make_pair(seta[i],setb[i]);
return count;
}

这里:

  • n 是数组的大小,
  • seta[] 包含对中第一个数字的索引和
  • setb[] 包含对中第二个数字的索引。

我使用O(count*n) 来计算每对的第二个数字的索引。

有没有更有效的方法来实现这一点?

【问题讨论】:

  • 添加了基于语法的C++标签;如果我的猜测是错误的,请更正。

标签: c++ algorithm data-structures


【解决方案1】:

为每个值存储具有该值的索引列表可能是个好主意:

const int MAX_VAL = 5;
std::vector<std::list<int>> mylist(MAX_VAL);
for (i = 0; i < n; ++i)
    mylist[arr[i]].push_back(i);

然后,对于每个值,找到“互补”值,并打印可以找到该值的所有索引的列表。

for(i=0;i<n;++i){
    a = arr[i];
    b = sum - a;
    for (auto j: mylist[b])
        make_pair(i, j); // whatever you want to do with this pair of indices...
}

检查i &lt;= j 以避免重复打印同一对可能是值得的。

请注意,一般情况下的复杂度必须为O(count*n):最坏的情况是由相同数字组成的数组:

数组:1、1、1、1、1

总和:2

答案:(0, 0), (0, 1), (0, 2), ..., (4, 4)

打印复杂度:O(n^2),或O(count*n),因为这里count 等于n

【讨论】:

  • 感谢您的回复,所以没有小于 O(count*n) 的解决方案.. 所以我该如何解决这个问题,我必须检查我可以达到两个数字的步数如果我从两端开始遍历,或者从左侧开始遍历,或者从右侧开始遍历,其总和为“x”。
  • @avinashse 我不明白您的回复,但您似乎在这里提出了不同的问题。如果您想解决其他问题,请单独发帖。
【解决方案2】:

这与 anatolyg 的答案相同,但使用 unordered_map 编码。

#include <iostream>
#include <list>
#include <unordered_map>

using namespace std;

void FindPairs(int arr[],int n, int sum, list<pair<int,int>> *pindex) {
  unordered_map<int,list<int>> etoi; // map entry to list of indices
  for( int i=0 ; i<n ; ++i ) etoi[arr[i]].push_back(i);
  for( int i=0 ; i<n ; ++i )
  {
    unordered_map<int,list<int>>::iterator it = etoi.find(sum-arr[i]);
    if( it != etoi.end() ) for( auto j: it->second )
      if( i < j ) pindex->push_back(make_pair(i,j));
  }
}

int main()
{
  int arr[5] = { 1, 2, 3, 4, 2 };
  int sum = 5;

  list<pair<int,int>> index;
  FindPairs( arr, sizeof(arr)/sizeof(int), sum, &index );
  for( auto p: index ) cout << '('<<p.first<<','<<p.second<<") ";
  cout << endl;
}

输出:

(0,3) (1,2) (2,4)

【讨论】:

  • 感谢您的回复,我在第一种方法中使用了 unordered_set,但我担心的是时间,因此我回到了数组 seta 和 setb
猜你喜欢
  • 2018-08-12
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
相关资源
最近更新 更多