Если у меня есть вектор вектора, назовем его:

vector<vector<int> > data;

А в данных есть числа вроде

0 1
0 3
0 4
1 0
1 2
1 5
3 0

Как я мог избавиться от данных, которые являются противоположностью самих себя? Например: 0 1 и 1 0, и я хотел бы избавиться от 1 0, потому что я уже видел 0 1. Другой пример: 0 3 и 3 0, и я хотел бы избавиться от 3 0, потому что я уже видел 0 3.

Таким образом, данные будут такими:

0 1
0 3
0 4
1 2
1 5

Какой способ сделать это проще всего?

1
Mdjon26 1 Апр 2014 в 21:30

4 ответа

Лучший ответ

Вы можете вставить векторы в набор и проверить, есть ли реверс уже в наборе. Что-то вроде этого:

Версия C ++ 11:

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

vector<int> myrev(vector<int>& f)
{
  vector<int> s;
  s.push_back(f[1]);
  s.push_back(f[0]);
  return s;
}
int main()
{
  vector<vector<int> > data={{0,1},{0,3},{0,4},{1,0},{1,2},{1,5},{3,0},{1,0}};
  set<vector<int> > unique_data;
  for(auto& x: data)
  {
    if(unique_data.find(myrev(x))==unique_data.end())
      unique_data.insert(x);
  }
  for(auto& x: unique_data)
  {
    cout << x[0] << ":" << x[1] << endl;
  }
  return 0;
}

Версия C ++ 98:

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

vector<int> myrev(vector<int>& f)
{
  vector<int> s;
  s.push_back(f[1]);
  s.push_back(f[0]);
  return s;
}
int main()
{
  vector<vector<int> > data;
  //lame C++98 initialization of the vector
  vector<int> tmp(2);
  tmp[0]=0;tmp[1]=1;
  data.push_back(tmp);
  tmp[0]=0;tmp[1]=3;
  data.push_back(tmp);
  tmp[0]=0;tmp[1]=4;
  data.push_back(tmp);
  tmp[0]=1;tmp[1]=0;
  data.push_back(tmp);
  tmp[0]=1;tmp[1]=2;
  data.push_back(tmp);
  tmp[0]=1;tmp[1]=5;
  data.push_back(tmp);
  tmp[0]=3;tmp[1]=0;
  data.push_back(tmp);

  set<vector<int> > unique_data;
  for(vector<vector<int> >::iterator x=data.begin(); x!=data.end(); x++)
  {
    if(unique_data.find(myrev(*x))==unique_data.end())
      unique_data.insert(*x);
  }
  for(set<vector<int> >::iterator x=unique_data.begin(); x!=unique_data.end(); x++)
  {
    cout << (*x)[0] << ":" << (*x)[1] << endl;
  }
  return 0;
}
1
Johnny Mnemonic 1 Апр 2014 в 20:31

Поскольку вы, вероятно, захотите распечатать значения без их противоположностей, вы можете сделать это:

for each pair:
    if it exists in the HashMap:
       do nothing
    else
        add the opposite to a HashMap 
        print the pair
1
Bartlomiej Lewandowski 1 Апр 2014 в 17:47

Если вы можете позволить себе использовать много памяти, а максимальный размер целых чисел невелик, как в вашем примере, я бы просто создал битовый вектор, достаточно большой, чтобы вместить все пространство поиска. Вычислить индекс в этот битовый вектор из обоих входных чисел.

int N_POSSIBLE_PAIRS = (1 << MAX_BITS) * (1 << MAX_BITS);

// vector<bool> is specialized - it only uses 1 bit per entry
std::vector<bool> bitset(N_POSSIBLE_PAIRS);

int index = (first << MAX_BITS) | second;

// in a loop,
if (bitset[index]) {
    // duplicate
}
else {
    int reverse_index = (second << MAX_BITS) | first;
    bitset[index] = true;
    bitset[reverse_index] = true;
}

На самом деле это тратит вдвое больше места - при необходимости вы можете исправить это с помощью более сложной схемы индексации.

Если максимальный размер целых чисел слишком велик, или вы ограничены в памяти, или вы просто предпочитаете экономить с памятью, тогда я бы отсортировал пары лексикографически и использовал двоичный поиск для проверки дубликатов. .

Также возможно, что мое предложение будет плохо работать с разреженными данными, потому что оно не подходит для кеширования.

1
japreiss 1 Апр 2014 в 18:40

Попробуйте это (при условии, что в вашем списке нет отрицательных чисел, и из соображений экономии места числа не слишком большие):

1) Создайте двумерную сетку с битовым набором размером MxM (где M - максимальное ожидаемое число). Установите каждый бит в сетке на 0

2) Для каждой пары чисел (x, y):

check if grid(x,y) is 1.  If yes then you have a duplicate
else
check if grid(y,x) is 1.  If yes then you have a duplicate.
set grid(x,y) and grid(y,x) to 1
0
PaulMcKenzie 1 Апр 2014 в 18:22