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
}