Remove Letter To Equalize Frequency

🏠 ⬅️ ➑️

You are given a 0-indexed string word, consisting of lowercase English letters. You need to select one index and remove the letter at that index from word so that the frequency of every letter present in word is equal.

Return true if it is possible to remove one letter so that the frequency of all letters in word are equal, and false otherwise.

Note:

  • The frequency of a letter x is the number of times it occurs in the string.
  • You must remove exactly one letter and cannot chose to do nothing.

Example 1:

Input: word = "abcc " Output: true Explanation: Select index 3 and delete it: word becomes "abc " and each character has a frequency of 1.

Example 2:

Input: word = "aazz " Output: false Explanation: We must delete a character, so either the frequency of "a " is 1 and the frequency of "z " is 2, or vice versa. It is impossible to make all present letters have equal frequency.

Constraints:

  • 2 <= word.length <= 100
  • word consists of lowercase English letters only.

Note: This problem is from LeetCode.
❌ Compiled
❌ Executed
❌ Correct
program main
    implicit none

    integer :: i, j, k
    logical :: result
    character(len=100) :: word

    ! Example 1
    word = 'abcc'
    result = solve(word)
    if (result) then
        print *, 'Example 1: ', word
    else
        print *, 'Example 1: ', 'FAIL'
    end if

    ! Example 2
    word = 'aazz'
    result = solve(word)
    if (.not. result) then
        print *, 'Example 2: ', word
    else
        print *, 'Example 2: ', 'FAIL'
    end if

contains

    function solve(word) result(result)
        implicit none
        character(len=*), intent(in) :: word
        integer :: freq(26)
        logical :: result

        result = .false.

        ! Count the frequency of each letter
        do i = 1, len(word)
            freq(ichar(word(i:i)) - ichar('a') + 1) = freq(ichar(word(i:i)) - ichar('a') + 1) + 1
        end do

        ! Check if there is any letter with frequency > 1
        do i = 1, 26
            if (freq(i) > 1) then
                result = .true.
                exit
            end if
        end do

        ! If there is no letter with frequency > 1, check if there is any letter with frequency < 1
        if (.not. result) then
            do i = 1, 26
                if (freq(i) < 1) then
                    result = .true.
                    exit
                end if
            end do
        end if

        ! Remove the letter with frequency > 1
        if (result) then
            do i = 1, len(word)
                if (ichar(word(i:i)) - ichar('a') + 1 == maxval(freq)) then
                    word(i:i) = ' '
                    exit
                end if
            end do
        end if

        ! Remove the letter with frequency < 1
        if (.not. result) then
            do i = 1, len(word)
                if (ichar(word(i:i)) - ichar('a') + 1 == minval(freq)) then
                    word(i:i) = ' '
                    exit
                end if
            end do
        end if

        ! Check if the frequency of every letter is equal
        do i = 1, 26
            if (freq(i) /= 1) then
                result = .false.
                exit
            end if
        end do

    end function solve

end program main
βœ… Compiled
❌ Executed
❌ Correct
module letter_frequency

implicit none

contains

function solve(word) result(output)

character(len=*), intent(in) :: word
logical :: output

integer :: i, j, count(26)

output = .false.

! Initialize the count array
count = 0

! Count the frequency of each letter
do i = 1, len(word)
    count(ichar(word(i:i)) - ichar('a')) = count(ichar(word(i:i)) - ichar('a')) + 1
end do

! Check if the frequency of each letter is equal
do i = 1, 26
    if (count(i) == 0) cycle
    if (count(i) /= count(1)) exit
end do

! If the frequency of each letter is equal, return true
if (i == 27) then
    output = .true.
end if

end function solve

end module letter_frequency

program main

use letter_frequency

implicit none

character(len=100) :: word

! Test case 1
word = "abcc "
if (solve(word)) then
    write (*,*) "Test case 1: Pass"
else
    write (*,*) "Test case 1: Fail"
end if

! Test case 2
word = "aazz "
if (solve(word)) then
    write (*,*) "Test case 2: Pass"
else
    write (*,*) "Test case 2: Fail"
end if

! Test case 3
word = "abcdefghijklmnopqrstuvwxyz"
if (solve(word)) then
    write (*,*) "Test case 3: Pass"
else
    write (*,*) "Test case 3: Fail"
end if

! Test case 4
word = "aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnn"
if (solve(word)) then
    write (*,*) "Test case 4: Pass"
else
    write (*,*) "Test case 4: Fail"
end if

! Test case 5
word = "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyyzzz"
if (solve(word)) then
    write (*,*) "Test case 5: Pass"
else
    write (*,*) "Test case 5: Fail"
end if

end program main
🌐 Data from online sources
def can_equal_frequency(word: str) -> bool:
    freq = {}
    for c in word:
        freq[c] = freq.get(c, 0) + 1

    count_freq = {}
    for f in freq.values():
        count_freq[f] = count_freq.get(f, 0) + 1

    if len(count_freq) != 2:
        return False

    a, acount = next(iter(count_freq.items()))
    b, bcount = next(reversed(list(count_freq.items())))

    return (acount == 1 and (a - 1 == b or a == 1)) or (bcount == 1 and (b - 1 == a or b == 1))
  1. First, we create a frequency map freq that counts the frequency of each character in the given word.
  2. Then, we create another map count_freq that counts the frequencies of the values in the freq map.
  3. If the size of count_freq is not 2, return false since we must remove exactly one character.
  4. If the size of count_freq is 2, we iterate through the items of the count_freq map.
  5. We check if the map contains a single entry with frequency 1 and either the other frequency is one less than the single entry frequency or it is 1.
  6. If either of the above two conditions is met, we can remove one character so that the remaining letters have equal frequencies. In this case, we return true. Otherwise, we return false.
🌐 Data from online sources
#include <unordered_map>

bool canEqualFrequency(std::string word) {
    std::unordered_map<char, int> freq;
    for (char c : word) {
        freq[c]++;
    }

    std::unordered_map<int, int> count_freq;
    for (auto &[c, f] : freq) {
        count_freq[f]++;
    }

    if (count_freq.size() != 2) {
        return false;
    }

    auto it = count_freq.begin();
    auto &[a, acount] = *it;
    it++;
    auto &[b, bcount] = *it;

    return (acount == 1 && (a - 1 == b || a == 1)) || (bcount == 1 && (b - 1 == a || b == 1));
}
  1. First, we create a frequency map freq that counts the frequency of each character in the given word.
  2. Then, we create another map count_freq that counts the frequencies of the values in the freq map.
  3. If the size of count_freq is not 2, return false since we must remove exactly one character.
  4. If the size of count_freq is 2, we iterate through the items of the count_freq map.
  5. We check if the map contains a single entry with frequency 1 and either the other frequency is one less than the single entry frequency or it is 1.
  6. If either of the above two conditions is met, we can remove one character so that the remaining letters have equal frequencies. In this case, we return true. Otherwise, we return false.