algorithm - Finding union of 2 sorted arrays (with duplicates) -
i'm trying find union of 2 sorted arrays (with duplicates) feel i'm not coming elegant code (what have works btw, feel can reduce lines of code). lets have 2 vectors = {1,3,3,4,4,4,5,7} , b = {1,3,3,3,5,5,5,6,8,9} , want store union in vector called unionvector (which 1,3,4,5,6,7,8,9)
here's code:
#include <iostream> #include <vector> using namespace std;  // prints contents of vector void printvector(vector<int> a){   if(a.size() == 0)     return;   else{     for(int = 0; < a.size(); i++)       cout << a[i] << '\t';   }   cout << endl; }  // print union of 2 sorted arrays duplicates void printunion(int *a, int asize, int *b, int bsize){   if(asize == 0 && bsize == 0)     return;   else{      vector<int> unionvector;      int = 0;     int j = 0;     int last = 0;      // insert smaller of first element regardless     if(a[i] < b[j]){       unionvector.push_back(a[i]);       i++;     }     else if (b[j] < a[i]){       unionvector.push_back(b[j]);       j++;     }     else{// both equal numbers        unionvector.push_back(a[i]);       i++;       j++;     }      // traverse both loops 1 increment @ time     while(i < asize && j < bsize){       last = unionvector[unionvector.size() - 1];        if(a[i] < b[j]){         if(last != a[i])           unionvector.push_back(a[i]);         i++; // increment in either case       }       else if(b[j] < a[i]){         if(last != b[j])           unionvector.push_back(b[j]);         j++;       }       else{         // both of numbers equal         if(last != a[i])           unionvector.push_back(a[i]);         i++;         j++;       }     }      // lets if 1 array wasn't complete     while(i < asize){       last = unionvector[unionvector.size() - 1];        if(last != a[i])         unionvector.push_back(a[i]);       i++;     }      while(j < bsize){       last = unionvector[unionvector.size() - 1];        if(last != b[i])         unionvector.push_back(b[j]);       j++;     }      printvector(unionvector);   } }  int main(){   int a[] = {1,3,3,4,4,4,5,7};   int b[] = {1,3,3,3,5,5,5,6,7,7,8,9};    printunion(a,8,b,12);    return 0; }   thing since there can duplicates check element inserted last element inserted in unionvector. need make sure don't try 'last' element when unionvector empty, thats why i'm inserting 1 element in unionvector anyways. appreciate if can suggest way can check without needing insert 1 element first (i thinking of having flag variable checks if unionvector empty or not, feel messy)
edit 1:
- this isn't homework problem. practising interviews
 
edit 2:
- i can't use built in functions
 
edit 3:
- some people getting confused if c++ position. can use language want
 
if both arrays sorted, it's matter of skipping ahead 1 iterator or other or both if there's match.
so like:
void printunion(int* a, int asize, int* b, int bsize) {     int *aend = + asize, *bend = b + bsize;     std::vector<int> unionvec;      (; != aend; ) {         if (b == bend) {             // copy of             while (a != aend) {                 unionvec.push_back(*a);                 = std::upper_bound(a + 1, aend, *a);             }             break;         }          if (*b < *a) {             unionvec.push_back(*b);             b = std::upper_bound(b + 1, bend, *b);         }          else {             unionvec.push_back(*a);             if (*b == *a) {                 b = std::upper_bound(b + 1, bend, *b);             }             = std::upper_bound(a + 1, aend, *a);         }     }      // copy of b     while (b != bend) {         unionvec.push_back(*b);         b = std::upper_bound(b + 1, bend, *b);     }      printvector(unionvec); }   if can't use upper_bound directly, implement function yourself. copying implementation this reference:
template<class forwardit, class t> int* upper_bound(int* first, int* last, const int value) {     int* it;     int count = last - first;     int step;      while (count > 0) {         = first;          step = count / 2;          += step;         if (value >= *it) {             first = ++it;             count -= step + 1;         }         else {             count = step;         }     }      return first; }   or non-binary-search version:
int* upper_bound(int* first, int* last, const int value) {     (; first < last && *first == value; ++first) {         ;     }      return first; }   now that's pretty verbose, , that's why standard provides algorithm directly set_union:
void printunion(int* a, int asize, int* b, int bsize) {     std::vector<int> unionvec;      // union     std::set_union(a, + asize, b, b + bsize, std::back_inserter(unionvec));      // remove dupes     unionvec.erase(std::unique(unionvec.begin(), unionvec.end()), unionvec.end());      printvector(unionvec); }      
Comments
Post a Comment