1

Is there any way to find size of union of two sets. I know can do this

vector < int > s3( s1.size() , s2.size() ); 
auto it=set_union( s1.begin() , s1.end() , s2.begin() ,s2.end(), s3.begin());
int size = it - s3.begin();

print size

example

s1 = {2 4 5 6}   size 4

s2 = {1 4 5 9 10}  size 5

s3 = {1 2 4 5 6 9 10}  size 7

complexity of set_union is 2*(s1 size + s2 size)-1

Is there any other method to get size of union of two sets faster method, I just need the size do not want the values of new union set formed. If you know a faster method please suggest.

danglingpointer
  • 4,708
  • 3
  • 24
  • 42
Shaurya Uppal
  • 3,410
  • 31
  • 31
  • If the method I stated is the only method possible please tell that too. – Shaurya Uppal Jun 03 '17 at 18:39
  • How could one work out the size of a set without knowing the contents of the set? Guess work perhaps – Ed Heal Jun 03 '17 at 18:39
  • s1 and s2 are already known s3 is using space and time both any this be reduced – Shaurya Uppal Jun 03 '17 at 18:41
  • Please explain your comment – Ed Heal Jun 03 '17 at 18:42
  • Reference from where I studied-> http://www.cplusplus.com/reference/algorithm/set_union/ I am trying to solve a question that on requires size of union set formed. with set_union I am utilizing space and time both. I am getting a TLE for that question so I thought may be there is a better method to find size of set. – Shaurya Uppal Jun 03 '17 at 18:45
  • 1
    You could iterate over both sets for an O(n) solution with no extra space. Would that be good enough? – Beta Jun 03 '17 at 19:01

2 Answers2

1

You can just put a counting iterator in last argument to set_union. E.g.

int count = 0;
it=set_union( s1.begin() , s1.end() , s2.begin() ,s2.end(), boost::make_function_output_iterator([&count](int){ ++count; })); 

Or a non-boost equivalent of that output iterator

struct counter {
    using difference_type = void;
    using value_type = void;
    using pointer = void;
    using reference = void;
    using iterator_category = std::output_iterator_tag;
    int count = 0;
    void operator&(int) { ++count }
    counter& operator++ { return *this; }
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • 1
    OP hasn't tagged this question as [tag:boost], so I would at least specify, that the answer is [tag:boost] only. – Zereges Jun 03 '17 at 22:12
  • I've given an example of expanding the lambda into that template manually – Caleth Jun 04 '17 at 08:02
0

One obvious way is to perform the same iteration set_union does but instead of copying the elements, just bump up a counter. That leaves the time complexity unchanged but eshews space usage completely.

Theoretically, one could devise an OutputIterator that just counts the elements so that set_union algorithm could be reused. Whether that is worth the hassle of making your iterator quack exactly the way STL expects it to is a different question... Reimplementing set_union to do just counting might be easier.

Tomek Sowiński
  • 863
  • 5
  • 16