I did a little trickery here to avoid the nested loop and make the code a bit more efficient. Here is the code:
bool UBullCowCartridge::IsIsogram(const FString& Word) const
{
bool bIsIsogram = true;
std::unordered_set<TCHAR> Characters;
for (const TCHAR Character : Word)
{
if (Characters.find(Character) != Characters.end())
{
bIsIsogram = false;
break;
}
else
{
Characters.insert(Character);
}
}
return bIsIsogram;
}
A bit of explanation here for those who need it. First, I use a range-based for loop instead of a regular for loop, but I did so as a style choice, not a hardcore efficiency thing. What does matter though is that I use a data structure known as an unordered set to store each character that I find, and then as I move on to the following character I check to see if that new character has already been found (and thus exists in my set). I chose an unordered set specifically because it has a constant look-up time and thus does not noticeably impact the run time of my function. Why this is more efficient gets into Big-O territory, but the simplified answer is that the number of comparisons my function makes at most is less than the nested loop solution’s number of comparisons at most.
The one thing that is impacted here is the amount of memory used. Since I save the characters in a separate data structure, this essentially increases the memory usage by the number of characters in the word at most. If you are in a memory constrained environment, this might not be ideal. But for most cases (especially in game development) memory constraints are not so tight as to make this a non-viable solution.