Remove anagrams from vector I was asked to solve the following exercise:

Given an input vector&lt;string&gt;, I have to find the anagrams and return a vector&lt;string&gt; with only the strings that are not an anagram from other strings in the vector.

Example:

Input vector:

"code","doce","framy","frame","sad","cat","frema"


Output:

"code","framy","sad","cat"


Here, the anagram "frame" == "frema" is removed. All words which are anagrams from one another are removed.

My solution is to sum the ASCII values from the strings, if two strings are equal, then I sort it to check for equality.

#include &lt;iostream&gt;
#include &lt;bits/stdc++.h&gt;
#include &lt;algorithm&gt;    // std::sort

using namespace std::chrono;
using namespace std;

int sumASCII(string input) {

    int i;
    int sum = 0;
    int size = input.size();

    for( i = 0; i &lt; size; i++) {

        sum+=(int)input[i];
    }

    return sum;
}

int sortStringAndCompare(string &amp;a, string &amp;b)
{
   sort(a.begin(), a.end());
   sort(b.begin(), b.end());
   return a.compare(b);
}

vector&lt;string&gt; funWithAnagrams(vector&lt;string&gt; &amp;text) {

    bool anagram = false;
    int i;
    int size = text.size();
    int sumCurr = 0;
    int sumPrev = 0;
    int k = 0;
    int originalSize = 0;

    string copyA;
    string copyB;

    vector&lt;string&gt; originalStrings;

    originalStrings.push_back(text[0]);

    for( i = 1 ; i &lt; size;  i++ ) {
        sumCurr = sumASCII(text[i]);
        originalSize = originalStrings.size();

        for( k = 0; k &lt; originalSize; k++ ) {


            if(originalStrings[k].size() == text[i].size() ) {
                sumPrev = sumASCII(originalStrings[k]);

                if(sumPrev == sumCurr) {// means it found a possible anagram.

                    copyA = originalStrings[k];
                    copyB = text[i];
                    if(sortStringAndCompare(copyA,copyB) == 0)
                    {
                        anagram = true;
                        break;
                    }
                }
                else
                    anagram = false;
            }
            else {
                anagram = false;
            }

        }
        if(!anagram) {
            originalStrings.push_back(text[i]);
            }
    }

    return originalStrings;
}

int stringCompare(std::string a,std::string b)
{
    return a.compare(b);

}

void print(std::vector&lt;string&gt; const &amp;input)
{
    int size = input.size();
    printf("[ ");
    for (int i = 0; i &lt; size; i++) {
        std::cout &lt;&lt; input.at(i) &lt;&lt; ' ';

        if(i &lt; (size-1))
            printf(",");
    }

    printf(" ]");
}

int main() {

    printf("TEST STARTED\n");
    vector&lt;string&gt; input{"doceframe","code", "doce","ecod","framer","frame", "frema","cat","sad"};
    vector&lt;string&gt; out;

    // Get starting timepoint
    auto start = high_resolution_clock::now();
    out = funWithAnagrams(input);
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast&lt;microseconds&gt;(stop - start);

    cout &lt;&lt; "Time taken by function: " &lt;&lt; duration.count() &lt;&lt; " microseconds" &lt;&lt; endl;
    printf("\n \n");
    print(out);
    printf("\n");

    printf("TEST ENDED\n");

    return 0;

}


My program is not the best in terms of memory, i shall improve it. But my task, at the moment, is to develop the fastest algorithm possible. How can I improve it?
You are on the right track, but the code does need a lot of attention.


Never go for #include &lt;bits/stdc++.h&gt; 

Same goes for using namespace std; Both will lead you into a lot of trouble for zero gain. Only include what you need and use proper qualifications

#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;


Note that I also sorted the includes alphabetically so it is easy to see what is already included
You should pass by value whenever it is possible. However std::string is no such case. Luckily we have std::string_view since C++17 so you should almost always prefere this to passing a std::string, e.g

int sumASCII(const std::string_view input) {    
    int i;
    int sum = 0;
    int size = input.size();

    for( i = 0; i &lt; size; i++) {
        sum+=(int)input[i];
    }

    return sum;
}


Same for all the other functions. Your strings are stored in the original vector so there is no possibility for a dangling reference. That said you should definitely read up on ownership and view-like types
Use a formatter. Your formatting is highly unregular. You should pick a clang-format style you are comfortable with and use that everywhere.
Use range-based loops when possible

int sumASCII(const std::string_view input) {    
    int sum = 0;   
    for (const char character : input) {
        sum += (int)character;
    }    
    return sum;
}

Do not use C-style casts. C++ has a wide variety of specialized casts that do what they are supposed to do and not more. In the above case static_cast is sufficient

int sumASCII(const std::string_view input) {    
    int sum = 0;   
    for (const char character : input) {
        sum += static_cast&lt;int&gt;(character);
    }    
    return sum;
}

Use the proper algorithms

The STL provides a wide range of algorithms that is not only incredibly powerfull but also is often highly optimized and correct with respect to various corner cases.

int sumASCII(const std::string_view input) {
    return std::accumulate(std::begin(input), std::end(input), 0);
}


Note that you might want to test this with proper warnings. 
Consider const correctness.

One of the most difficult parts of programming is keeping all the moving parts in your head. The more explicit you are about what is immutable the easier it is to reason about the code. So use const whenever possible and cbegin and cend too. (Even if in this case it does exactly the same it provides additional information to the reader)

int sumASCII(const std::string_view input) {
    return std::accumulate(std::cbegin(input), std::cend(input), 0);
}

Keep control flow as simple as possible.

Another hard part of software engineering is keeping track of control flow. Try to minimize indentations as much as possible to keep the code clean and easily readable. As an example this is what you wrote

for( i = 1 ; i &lt; size;  i++ ) {
    sumCurr = sumASCII(text[i]);
    originalSize = originalStrings.size();
    for( k = 0; k &lt; originalSize; k++ ) {
        if(originalStrings[k].size() == text[i].size() ) {
            sumPrev = sumASCII(originalStrings[k]);
            if(sumPrev == sumCurr) {// means it found a possible anagram.
                copyA = originalStrings[k];
                copyB = text[i];
                if(sortStringAndCompare(copyA,copyB) == 0)
                {
                    anagram = true;
                    break;
                }
            }
            else
                anagram = false;
        }
        else {
           anagram = false;
        }

    }
    if(!anagram) {
        originalStrings.push_back(text[i]);
    }
}


It is hard to keep track of the different conditions in thi loop and what it actually does so lets try to simplify it with some early returns:

for( i = 1 ; i &lt; size;  i++ ) {
    anagram = false;
    sumCurr = sumASCII(text[i]);
    originalSize = originalStrings.size();
    for (const string_view newString : originalStrings) {
        if(newString.size() != text[i].size() ) {
            continue;
        }

        sumPrev = sumASCII(newString);
        if(sumPrev != sumCurr) {
            continue;
        }

        copyA = originalStrings[k];
        copyB = text[i];
        if(sortStringAndCompare(copyA,copyB) == 0) {
            anagram = true;
            break;
        }
    }

    if(!anagram) {
        originalStrings.push_back(text[i]);
    }
}


I hope you agree that this is much easier to read.
Think about the proper data structures.

You are searching for a reoccuring pattern. This is usually done via an associative container. The STL knows std::unordered_map and std::map. You should use those.

The first thing you need is a container of histograms,. You wantunique ones so you should go for a set

std::unordered_set&lt;someHistogramThing&gt; histograms;


The second thing you want to do is to count the characters in the string. Again a map is the simplest solution

std::unordered_map&lt;char, std::size_t&gt; charCount;


Lets have a look at how we get there;

std::unordered_map&lt;char, std::size_t&gt; countCharacters(const std::string_view input) {
    std::unordered_map&lt;char, std::size_t&gt; charCount;
    for (const char character : input) {
        charCount[character]++;
    }
    return charCount;
}


For any word this gives us a histogram of the occurences of characters in that word. Two words are an anagram if they have the same histogram. So lets see if we can put it together.

std::vector&lt;std::string&gt; removeAnagrams(const std::vector&lt;std::string&gt;&amp; input) {
    std::vector&lt;std::string&gt; result;
    std::unordered_set&lt;std::unordered_map&lt;char, std::size_t&gt;&gt; histograms;
    for (const std::string&amp; newWord : input) {
        const auto[it, notAnagram] = histograms.insert(countCharacters(newWord));
        if (notAnagram) {
            result.push_back(word);
        } 
    }
}

Usetype aliases to give your data structures better names

using CharacterHistogram = std::unordered_map&lt;char, std::size_t&gt;;
using HistogramSet = std::unordered_set&lt;CharacterHistogram&gt;;


If we put that all together we get

#include &lt;string&gt;
#include &lt;string_view&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;unordered_set&gt;

using CharacterHistogram = std::unordered_map&lt;char, std::size_t&gt;;
using HistogramSet = std::unordered_set&lt;CharacterHistogram&gt;;

CharacterHistogram countCharacters(const std::string_view input) {
    CharacterHistogram charCount;
    for (const char character : input) {
        charCount[character]++;
    }
    return charCount;
}

std::vector&lt;std::string&gt; removeAnagrams(const std::vector&lt;std::string&gt;&amp; input) {
    std::vector&lt;std::string&gt; result;
    HistogramSet histograms;
    for (const std::string&amp; newWord : input) {
        const auto[it, notAnagram] = histograms.insert(countCharacters(newWord));
        if (notAnagram) {
            result.push_back(word);
        } 
    }
}