Fizz Buzz Problem

Difficulty: Easy, Asked-In: Google, Microsoft, Amazon

Key takeaway: FizzBuzz game is a popular problem that is more about learning the basic programming concepts such as if-else, loops, string operations, mathematical operations, optimizations, etc.

Let’s understand the problem!

This game is played in a group, where players take turns to say the next number in a sequence, counting one at a time.

  • If the number is divisible by 3, the player must say “Fizz” instead of the number itself.
  • If the number is divisible by 5, the player must say “Buzz”.
  • If the number is divisible by 3 and 5, the player must say “Fizz buzz”.

Given a number n, write a program that outputs the string representation of numbers from 1 to n. We need to return a string array as an output (1-indexed) where:

  • output[i] = "FizzBuzz" if i is divisible by 3 and 5.
  • output[i] = "Fizz" if i is divisible by 3.
  • output[i] = "Buzz" if i is divisible by 5.
  • output[i] = "i" if non of the above conditions are true.

Important note: before moving on to the solutions, we recommend trying this problem on paper for atleast 15 or 30 minutes. Enjoy problem-solving!

Example

Intput: n = 15

Output: ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz"]

Discussed solution approaches

  • Solution approach 1: Using modulus operation
  • Solution approach 2: Without using modulus operations
  • Solution approach 3: Using string concatenation
  • Solution approach 4: Using the hash table

Solution approach 1: Using modulus operation

Solution idea

The most basic solution is to run a loop from 1 to n and use the modulus operation. In this loop, we use a sequence of conditional statements to check whether each integer is divisible by 3 or 5 or both. When one of the conditional statements returns true, we store the appropriate string value at the ith index in the output[] string. Once the loop has been completed, we return the output[] string.

Solution steps

  1. We define an empty output[] string of size n.
  2. We run a loop from 1 to n and check divisibility by 3 or 5 or both.
  3. For i is divisible by both 3 and 5, we add string "FizzBuzz" at the ith index of the output string. 
  4. Else, if integer i is divisible by 3, we add "Fizz".
  5. Else, if integer i is divisible by 5, we add "Buzz".
  6. Else, we add the string value of integer i.

Solution pseudocode

string[] fizzBuzzGame(int n) 
{
    string output[n]    
    for (int i = 1; i <= n; i = i + 1) 
    { 
        if ((i % 3 == 0) && (i % 5 == 0))
            output[i] = "FizzBuzz"
        else if ((i%3) == 0)
            output[i] = "Fizz"
        else if ((i%5) == 0)
            output[i] = "Buzz"
        else
            output[i] = string.valueOf(i)
    }
    return output
}

Solution analysis

We are running a single loop and doing constant operations at each iteration. So time complexity = O(n). We are using constant extra space, so space complexity = O(1).

Note: The above code works perfectly but there are some limitations:

  • The statements i%3 == 0 and i%5 == 0 are repeated twice, making the code inefficient.
  • At the lowest level, modulo is a division operation that can be costly in terms of performance, especially for large integers.
  • It uses a lot of messy conditional statements, which are hard to maintain when the number of divisibility conditions increases in the problem.

Solution approach 2: Without using modulus operations

Now the critical question is: how do we think to solve the fizz buzz problem without using mod operation? Let's think!

When we explore each number from the start, then the word "Fizz" will appear after the cycle of 3. Similarly, the word "Buzz" will appear after the cycle of 5. Then what would be the scenario when both words come together? The answer is simple: "FizzBuzz" will appear after the cycle of 15 because 15 is the lowest number which is divisible by both 3 and 5. Think!

So using the above insight, let's track the appearance cycle of the words "Fizz" and "Buzz using two variables fizzCount and buzzCount. In the start, we initialize both variables with 0 and run a loop from i = 1 to n. At each iteration, we increment fizzCount and buzzCount by 1 and keep track of the cycle of 3 and 5.

  • We reset fizzCount = 0, when fizzCount == 3.
  • We reset buzzCount = 0 when buzzCount == 5.

Now there would be four scenarios:

  • fizzCount != 3 and buzzCount != 5: We need to store the string value of the number i at the ith index of the output string.
  • fizzCount == 3 and buzzCount != 5: We store the word "Fizz" at the ith index of the output string and set fizzCount = 0.
  • fizzCount != 3 and buzzCount == 5: We store the word "Buzz" at the ith index of the output string and set buzzCount = 0.
  • fizzCount == 3 and buzzCount == 5: We store the word "FizzBuzz" at the ith index of the output string and set both buzzCount and fizzCount equal to 0.

Solution pseudocode

string[] fizzBuzzGame(int n) 
{
    string output[n] 
    int fizzCount  = 0
    int buzzCount = 0
    for (int i = 1; i <= n; i = i + 1) 
    {
        fizzCount = fizzCount + 1
        buzzCount = buzzCount + 1
        if (fizzCount == 3 && buzzCount == 5)
        {
            output[i] = "FizzBuzz"
            fizzCount = 0
            buzzCount = 0
        }
        else if (fizzCount == 3)
        {
            output[i] = "Fizz"
            fizzCount = 0
        }
        else if (buzzCount == 5)
        {
            output[i] = "Buzz"
            buzzCount = 0
        }
        else
            output[i] = string.valueOf(i)
    } 
    return output
}

Solution analysis

We are running a single loop and doing constant operations at each iteration. So time complexity = O(n). We are using constant extra space, so space complexity = O(1).

Solution approach 3: Using string concatenation

Solution Idea

In the above solution, we are still using a lot of conditional statements. Now a critical question is: can we reduce the number of conditional statements in the loop? Let's think! 

For example, if the problem gets modified from FizzBuzz to FizzBuzzJazz i.e. store "Fizz" if the integer is 3, store "Buzz" if the integer is 5, and store "Jazz" if the integer is 7. If we try to solve this with the previous approach, then we need to check several conditions:

  • Divisible by 3, divisible by 5, divisible by 7
  • Divisible by 3 and 5, divisible by 3 and 7, divisible by 7 and 3
  • Divisible by 3 and 5 and 7, Not divisible by 3 or 5 or 7.

So if the FizzBuzz mappings increase, the number of conditional statements would grow exponentially in our code. So instead of checking for every possible combination of these conditional statements, we only check for divisibility by given numbers in the problem i.e. 3 and 5. If the number is divisible, we concatenate the corresponding string "Fizz" or "Buzz" to the output[] string.

So for FizzBuzz, we just check for two conditions. Similarly, for FizzBuzzJazz, we would have three conditions to check for divisibility. 

Solution steps

Step1: We define an empty output[] string of size n.

Step2: Now we run a loop from i = 1 to n. At each iteration:

  • We start by defining an empty string s
  • If i is divisible by 3, we add “Fizz” at the end of the empty string s. 
  • Similarly, if i is divisible by 5, we add “Buzz” at the end of the empty string s. 
  • Now we check string s is empty or not. If yes, we store the string value of integer i in the empty string s. 
  • Finally, we store the value of s at output[i].

Step 3: Once the loop is over, we return the output[] string as an output.

Solution pseudocode

string[] fizzBuzzGame(int n)  
{
    string output[n]   
    for (int i = 1; i <= n; i = i + 1) 
    {
        string s = ""
        if ((i%3) == 0)
            s = s + "Fizz"
        if ((i%5) == 0)
            s = s + "Buzz"
        if (s == "")
            s = s + string.valueOf(i)
            
        output[i] = s
    }
    return output
}

Solution analysis

We are running a single loop and doing constant operations at each iteration. So time complexity = O(n). We are using constant extra space, so space complexity = O(1).

Solution approach 4: Using a hash table

Solution Idea

This approach is an optimization over the previous approach. When the number of mappings is limited, approach 3 looks good. But the critical questions are: what if we need to add too many mappings? What if we need to change mapping or maybe delete a mapping? Are we going to change the code whenever we have a modification in the mappings? So one idea is clear: having a condition for every mapping is not feasible, or code might be difficult to maintain.

One idea is to insert all given mappings in a Hash Table in the form of key-value pair. Here the number is the key, and desired output string is the value.

For every number i = 1 to n, we go through every entry in the hash table. If the number is divisible by the key, we concatenate the corresponding hash value to the output string for the current number. This way, we can insert or delete mappings from the hash table without changing the code.

Solution steps

  • We insert all the mappings in a hash table. For the FizzBuzz problem, the hash table would look something like { (3, 'Fizz'), (5, 'Buzz') }. Similarly, for the FizzBuzzJazz problem, the hash table would look something like { (3, 'Fizz'), (5, 'Buzz'), (7, 'Jazz') }
  • We run a loop on the numbers from i = 1 to n. For every number i, we iterate over the hash table and check for divisibility with each key. If the number is divisible by the key, we concatenate the corresponding hash value to the output[] string for the current number.
  • Finally, we add the resulting string to the output[] string.

Solution pseudocode

string[] fizzBuzzGame(int n) 
{
    string output[n]    
    HashTable fizzBuzz
    fizzBuzz.insert(3, "Fizz")
    fizzBuzz.insert(5, "Buzz")
    for (int i = 1; i <= n; i = i + 1)
    {
        String s = ""
        for (Integer key : fizzBizz.keySet())
        {
            if ((i % key) == 0)
                s = s + fizzBizz.get(key)
        }
        if (s == "")
            s = s + string.valueOf(i)
        output[i] = s
    }
    return output
}

Solution analysis

  • The size of the hash table will be constant because we are storing a constant number of key-value pairs. Space complexity = O(1)
  • So at each iteration of the outer loop, we will be doing a constant number of operations. Time complexity = O(n)

Important note: we recommend transforming the above pseudo-codes into a favorite programming language (C, C++, Java, Python, etc.) and verifying all the test cases. Enjoy programming!

Critical ideas to think!

  • How will the time and space complexity of the above approaches affect when integer to string mapping in the problem will increase?
  • In approach 1, can we check the divisibility by 15 to print the "FizzBuzz" instead of checking the divisibility by both 3 and 5?
  • Can we come up with some other approaches to solve this problem?
  • Hash table works as an unordered dictionary which doe not preserve the order of keys. Can we use the ordered dictionary or BST to solve this problem? What would be the time complexity? Is it better than the hash table approach?
  • Instead of the hash table, can we use the ordered list of (divisor, string)?
  • Explore the library implementation of dictionaries in various programming languages. Do they have some extra capabilities to preserve the insertion order of elements?
  • Explore the several variations of the FizzBuzz problem.
  • Just for fun :) Write the worst but the working implementation of Fizz Buzz that you can think of!

Please write in the message below if you find anything incorrect, or you want to share more insight, or you know some different approaches to solve this problem. Enjoy learning, Enjoy algorithms!

More From EnjoyAlgorithms

Our weekly newsletter

Subscribe to get free weekly content on data structure and algorithms, machine learning, system design, oops design and mathematics.

Follow Us:

LinkedinMedium

© 2020 EnjoyAlgorithms Inc.

All rights reserved.