Skip to content

# Interview preparation kit, String Manipulation

## Sherlok and Valid Srings

• Thought: Run through the following steps

• (1) Collecting the statistic data of occurance of all the characters in the given string
• (2) Iterate through the map in (1), and count the occurance of occurance
• (3) In (1), (2) such as aaabbccc is a : 3, b : 2, c : 3, and the occurance of occurance is 3 : 2 and 2 : 1
• (4) Considering the situations
• (4-1) If there are > 2 kinds of occurances, such as aaabbccc, than we must at least 1 a and 1 c, which is not satisfiable
• (4-2) If only one kind of occurances, such as abcdefg, than already satisfiable
• The following has only 2 kinds of occurances.
• (4-3) If the occurance of lower frequency alphabet is only one, then we just easily remove that, such as aaab a^100b, removing one b satisfies the criterium.
• (4-4) If the higher frequency lower one is only 1 and that occurance of higher frequency is exactly 1, such as bbbcc, removing one b satisfies the criterium. But aaabbbcc is 3 : 2, 2 : 1, should at least remove one a and b, does not satisfies the criterium.
• (4-5) No matter the occurance of occurance, if higher frequency - lower frequency exceeds 1, then it fails, such as bbbbbbcc (bbbbbbc has been filtered in 4-3)
• (4-6) The rest failed
• Analysis:

• Time complexity: O(N), iterating the whole string and implement the statistical data
• Space complexity: O(N), by using a map data to store the statistical data.
string isValid(string s)
{
// step (1)
unordered_map<char, int> map_1; // stat data for character occurance
string res;
int n = s.size();

for(int i = 0; i < n; i++)
{
map_1[s[i]]++;
}

// step (2), (3)

map<int, int> freq_cnt; // order matters
for(unordered_map<char, int>::iterator it = map_1.begin() ;it != map_1.end(); it++)
{
freq_cnt[it -> second]++;
}
if(freq_cnt.size() > 2) // step 4-1
{
return "NO";
}
else if(freq_cnt.size() == 1) // all the same frequency, ex aabbccddee, we only have 2 : 5 // step 4-2
{
return "YES";
}

map<int, int>::iterator it = freq_cnt.begin();
int f1 = it -> first;
int lower_freq_cnt = it -> second;

map<int, int>::iterator it2 = ++it;
int f2 = it2 -> first;
int higher_freq_cnt = it2 -> second;

int lower_freq = min(f1, f2), higher_freq = max(f1, f2);

if(lower_freq == 1 && lower_freq_cnt == 1) // step 4-3
{
return "YES";
}
else if(higher_freq - lower_freq == 1 && higher_freq_cnt == 1) // step 4-4
{
return "YES";
}
else if(higher_freq - lower_freq > 1) // step 4-5
{
return "NO";
}

return "NO"; // step 4-6
}