Sherlock and the Valid String

  • + 0 comments

    Python 3 solution:

    def isValid(s):
        # Write your code here
        char_freq: dict[str, int] = {}
        freq_count: dict[int, int] = {}
        for char in s:
            char_freq[char] = char_freq.get(char, 0) + 1
        for freq in char_freq.values():
            freq_count[freq] = freq_count.get(freq, 0) + 1
        # reject if more than 2 different frequencies (-1 in any cannot become uniform)
        if len(freq_count.keys()) > 2:
            return "NO"
        # accept if all frequencies are the same / uniform
        if len(freq_count.keys()) == 1:
            return "YES"
        freqs: list[int] = list(sorted(freq_count.keys()))
        big_freq = freqs[1]
        small_freq = freqs[0]
        # edge case for smaller freq is single char
        if small_freq == 1 and freq_count[small_freq] == 1:
            return "YES"
        # when there is only 1 character type with freq = big_freq, 
        # and removing 1 of that char will make the freq_count uniform
        if freq_count[big_freq] == 1 and big_freq == small_freq + 1:
            return "YES"
        return "NO"
    

    Java 8 solution:

    public static String isValid(String s) {
    // Write your code here
        Map<Character, Long> charFreq = s.codePoints().mapToObj(x -> (char) x).collect(Collectors.groupingBy(x -> x, Collectors.counting()));
        Map<Long, Long> freqCount = charFreq.values().stream().collect(Collectors.groupingBy(x -> x, Collectors.counting()));
        int keySetSize = freqCount.size();
        // accept if all frequencies are the same / uniform
        if (keySetSize < 2) {
            return "YES";
        }
        // reject if more than 2 different frequencies (-1 in any cannot become uniform)
        if (keySetSize > 2) {
            return "NO";
        }
        Long[] freqs = freqCount.keySet().toArray(new Long[0]);
        int bigFreqIndex = freqs[1] > freqs[0] ? 1 : 0;
        long smallFreq = freqs[1 - bigFreqIndex];
        long bigFreq = freqs[bigFreqIndex];
        // edge case for smaller freq is single char
        if (smallFreq == 1 && freqCount.get(smallFreq) == 1) {
            return "YES";
        }
        // when there is only 1 character type with freq = big_freq, 
        // and removing 1 of that char will make the freq_count uniform
        if (bigFreq == smallFreq + 1 && freqCount.get(bigFreq) == 1l) {
            return "YES";
        }
        return "NO";
    }