【问题标题】:Compare vectors and delete vectors where all elements are already inside another vector比较向量并删除所有元素已经在另一个向量中的向量
【发布时间】:2012-10-23 17:02:22
【问题描述】:

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

假设我的向量中有 4 个这样的元素

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

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

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

【问题讨论】:

  • 我建议您自己进行研究并付出一些努力。
  • 您想彻底消除重复项吗?如果是,那么一种将所有向量都插入其中的集合可能是有意义的。
  • 好吧,我认为您的问题过于开放,但为了帮助您,std::remove 和 std::vector::erase 将成为您的朋友,可能 std:: set_intersect 和 std::back_inserter。如果您得到解决方案并需要帮助,我们可能会提供更多帮助。
  • 向量中的元素是否已排序?
  • "最快的算法是什么?" - 回答这个问题的唯一方法是在你的环境中运行每个算法,在你的数据集上。我们能做的最好的就是建议可能很快的算法,并让您选择最快的算法。

标签: c++ vector std


【解决方案1】:

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

#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} }));
}

【讨论】:

  • std::unordered_map 应该比 std::map 快。
  • "其中的所有值都已经在另一个元素中"。 IE。要求不是“唯一性”,而是“不包含”
  • 重新:唯一性。同意。但是对于给出的示例数据,“不在另一个元素内”和“唯一”是相同的。
【解决方案2】:

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

对于 [[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. 对于每个向量,计算每个值的容器的交集。如果结果交集中有多个项目(即不仅是自交集),则删除此类向量。

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    相关资源
    最近更新 更多