比较向量和删除向量,其中所有元素已经在另一个向量中

时间:2012-10-23 17:02:23

标签: c++ vector std

我使用向量向量来存储id-number,我想比较所有这些并删除其中所有值已经在另一个元素中的元素。

假设我的矢量中有4个元素,如此

[[1,2,3,4],[1,2,3],[3],[1,2,3,5]]

在此示例中,应删除第二个和第三个元素。

解决此问题的最快算法是什么?

2 个答案:

答案 0 :(得分:0)

这是一种可能的解决方案。

#include <vector>
#include <map>
#include <iostream>
#include <algorithm>

typedef std::vector<int> VI;
typedef std::vector<std::vector<int>> VVI;

VVI DeleteDups(VVI vvi) {
  std::map<int,int> map;

  for(auto const& vi : vvi)
    for(auto const& i : vi)
      ++map[i];

  vvi.erase(
    std::remove_if(begin(vvi), end(vvi),
      [&map](const VI& vi)->bool {
        for(int i : vi)
          if(map[i] == 1) return false;
        return true;
      }),
    end(vvi));
  return vvi;
}

void Dump(const VVI& vvi) {
  std::cout << "[";
  for(auto const& vi : vvi) {
    std::cout << "[";
    for(int i : vi)
      std::cout << i << ", ";
    std::cout << "], ";
  }
  std::cout << "]\n";
}

int main () {
  Dump(DeleteDups({ {1,2,3,4}, {1,2,3}, {3}, {1,2,3,5} }));
}

答案 1 :(得分:0)

这里解决方案满足“已经在另一个元素内部”的要求,而不仅仅是元素的“唯一性”。

对于[[1,2,3,4],[1,2,3],[3],[1,2,3,5]],输出为[[1,2,3,4] ,[1,2,3,5]]。

对于[[1,2,3,4],[1,2,3],[3,4],[1,2,3,5]],输出为[[1,2,3, 4],[1,2,3,5]]。

它的工作原理如下:

  1. 生成将值映射到其容器的矢量的地图
  2. 对于每个向量,计算每个值的容器的交叉点。如果结果交集中有多个项目(即不仅是自相交),则删除此类向量。

  3. #include <boost/container/vector.hpp>
    #include <boost/range/algorithm.hpp>
    #include <boost/assign/list_of.hpp>
    #include <boost/unordered_map.hpp>
    #include <boost/foreach.hpp>
    
    #include <iterator>
    #include <iostream>
    #include <ostream>
    #include <cstddef>
    #include <string>
    
    using namespace boost::assign;
    using namespace boost;
    using namespace std;
    
    template<typename VecVec,typename OutputIterator>
    void delete_included(const VecVec &vv,OutputIterator out)
    {
        typedef typename range_value<VecVec>::type vec_type;
        typedef typename const vec_type *vec_id;
        typedef typename range_value<vec_type>::type value_type;
    
        unordered_map<value_type,container::vector<vec_id> > value_in;
        container::vector<vec_id> all_vec_indexes;
        BOOST_FOREACH(const vec_type &vec,vv)
        {
            all_vec_indexes.push_back(&vec);
            BOOST_FOREACH(const value_type &value,vec)
            {
                value_in[value].push_back(&vec);
            }
        }
        container::vector<vec_id> included_in;
        container::vector<vec_id> intersect;
        BOOST_FOREACH(const vec_type &vec,vv)
        {
            included_in=all_vec_indexes;
            BOOST_FOREACH(const value_type &value,vec)
            {
                intersect.clear();
                set_intersection(included_in,value_in[value],back_inserter(intersect));
                swap(included_in,intersect);
                if(included_in.size()==1)
                    break;
            }
            if(included_in.size()==1)
            {
                *out=vec;
                ++out;
            }
        }
    }
    template<typename VecVec>
    void print(const VecVec &vv)
    {
        typedef typename range_value<VecVec>::type vec_type;
        typedef typename range_value<vec_type>::type value_type;
    
        cout << string(16,'_') << endl;
        BOOST_FOREACH(const vec_type &vec,vv)
        {
            copy(vec,ostream_iterator<const value_type&>(cout," "));
            cout << endl;
        }
    }
    
    int main(int argc,char *argv[])
    {
        container::vector<container::vector<int> > vv
        (list_of
            ( list_of (1)(2)(3)(4) )
            ( list_of (1)(2)(3) )
            ( list_of (3) )
            ( list_of (1)(2)(3)(5) )
        );
        print(vv);
    
        container::vector<container::vector<int> > result;
        delete_included(vv,back_inserter(result));
        print(result);
        return 0;
    }