Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using core interview patterns strategy.
You have the four functions:
printFizz that prints the word "fizz" to the console,printBuzz that prints the word "buzz" to the console,printFizzBuzz that prints the word "fizzbuzz" to the console, andprintNumber that prints a given integer to the console.You are given an instance of the class FizzBuzz that has four functions: fizz, buzz, fizzbuzz and number. The same instance of FizzBuzz will be passed to four different threads:
fizz() that should output the word "fizz".buzz() that should output the word "buzz".fizzbuzz() that should output the word "fizzbuzz".number() that should only output the integers.Modify the given class to output the series [1, 2, "fizz", 4, "buzz", ...] where the ith token (1-indexed) of the series is:
"fizzbuzz" if i is divisible by 3 and 5,"fizz" if i is divisible by 3 and not 5,"buzz" if i is divisible by 5 and not 3, ori if i is not divisible by 3 or 5.Implement the FizzBuzz class:
FizzBuzz(int n) Initializes the object with the number n that represents the length of the sequence that should be printed.void fizz(printFizz) Calls printFizz to output "fizz".void buzz(printBuzz) Calls printBuzz to output "buzz".void fizzbuzz(printFizzBuzz) Calls printFizzBuzz to output "fizzbuzz".void number(printNumber) Calls printnumber to output the numbers.Example 1:
Input: n = 15 Output: [1,2,"fizz",4,"buzz","fizz",7,8,"fizz","buzz",11,"fizz",13,14,"fizzbuzz"]
Example 2:
Input: n = 5 Output: [1,2,"fizz",4,"buzz"]
Constraints:
1 <= n <= 50Problem summary: You have the four functions: printFizz that prints the word "fizz" to the console, printBuzz that prints the word "buzz" to the console, printFizzBuzz that prints the word "fizzbuzz" to the console, and printNumber that prints a given integer to the console. You are given an instance of the class FizzBuzz that has four functions: fizz, buzz, fizzbuzz and number. The same instance of FizzBuzz will be passed to four different threads: Thread A: calls fizz() that should output the word "fizz". Thread B: calls buzz() that should output the word "buzz". Thread C: calls fizzbuzz() that should output the word "fizzbuzz". Thread D: calls number() that should only output the integers. Modify the given class to output the series [1, 2, "fizz", 4, "buzz", ...] where the ith token (1-indexed) of the series is: "fizzbuzz" if i is divisible by 3 and 5, "fizz" if i is divisible by 3 and not 5, "buzz"
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: General problem-solving
15
5
fizz-buzz)print-zero-even-odd)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
class FizzBuzz {
private int n;
public FizzBuzz(int n) {
this.n = n;
}
private Semaphore fSema = new Semaphore(0);
private Semaphore bSema = new Semaphore(0);
private Semaphore fbSema = new Semaphore(0);
private Semaphore nSema = new Semaphore(1);
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 3; i <= n; i = i + 3) {
if (i % 5 != 0) {
fSema.acquire();
printFizz.run();
nSema.release();
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 5; i <= n; i = i + 5) {
if (i % 3 != 0) {
bSema.acquire();
printBuzz.run();
nSema.release();
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 15; i <= n; i = i + 15) {
fbSema.acquire();
printFizzBuzz.run();
nSema.release();
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
nSema.acquire();
if (i % 3 == 0 && i % 5 == 0) {
fbSema.release();
} else if (i % 3 == 0) {
fSema.release();
} else if (i % 5 == 0) {
bSema.release();
} else {
printNumber.accept(i);
nSema.release();
}
}
}
}
// Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
// Auto-generated Go example from java.
func exampleSolution() {
}
// Reference (java):
// // Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
// class FizzBuzz {
// private int n;
//
// public FizzBuzz(int n) {
// this.n = n;
// }
//
// private Semaphore fSema = new Semaphore(0);
// private Semaphore bSema = new Semaphore(0);
// private Semaphore fbSema = new Semaphore(0);
// private Semaphore nSema = new Semaphore(1);
//
// // printFizz.run() outputs "fizz".
// public void fizz(Runnable printFizz) throws InterruptedException {
// for (int i = 3; i <= n; i = i + 3) {
// if (i % 5 != 0) {
// fSema.acquire();
// printFizz.run();
// nSema.release();
// }
// }
// }
//
// // printBuzz.run() outputs "buzz".
// public void buzz(Runnable printBuzz) throws InterruptedException {
// for (int i = 5; i <= n; i = i + 5) {
// if (i % 3 != 0) {
// bSema.acquire();
// printBuzz.run();
// nSema.release();
// }
// }
// }
//
// // printFizzBuzz.run() outputs "fizzbuzz".
// public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
// for (int i = 15; i <= n; i = i + 15) {
// fbSema.acquire();
// printFizzBuzz.run();
// nSema.release();
// }
// }
//
// // printNumber.accept(x) outputs "x", where x is an integer.
// public void number(IntConsumer printNumber) throws InterruptedException {
// for (int i = 1; i <= n; i++) {
// nSema.acquire();
// if (i % 3 == 0 && i % 5 == 0) {
// fbSema.release();
// } else if (i % 3 == 0) {
// fSema.release();
// } else if (i % 5 == 0) {
// bSema.release();
// } else {
// printNumber.accept(i);
// nSema.release();
// }
// }
// }
// }
# Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
from threading import Semaphore
class FizzBuzz:
def __init__(self, n: int):
self.n = n
self.fizzSemaphore = Semaphore(0)
self.buzzSemaphore = Semaphore(0)
self.fizzbuzzSemaphore = Semaphore(0)
self.numberSemaphore = Semaphore(1)
# printFizz() outputs "fizz"
def fizz(self, printFizz: 'Callable[[], None]') -> None:
for i in range(1, self.n + 1):
if i % 3 == 0 and i % 15 != 0:
self.fizzSemaphore.acquire()
printFizz()
self.numberSemaphore.release()
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n + 1):
if i % 5 == 0 and i % 15 != 0:
self.buzzSemaphore.acquire()
printBuzz()
self.numberSemaphore.release()
# printFizzBuzz() outputs "fizzbuzz"
def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n + 1):
if i % 15 == 0:
self.fizzbuzzSemaphore.acquire()
printFizzBuzz()
self.numberSemaphore.release()
# printNumber(x) outputs "x", where x is an integer.
def number(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1, self.n + 1):
self.numberSemaphore.acquire()
if i % 15 == 0:
self.fizzbuzzSemaphore.release()
elif i % 3 == 0:
self.fizzSemaphore.release()
elif i % 5 == 0:
self.buzzSemaphore.release()
else:
printNumber(i)
self.numberSemaphore.release()
// Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
use std::sync::Condvar;
use std::sync::Mutex;
struct FizzBuzz {
n: i32,
seq: (Mutex<i32>, Condvar),
}
impl FizzBuzz {
fn new(n: i32) -> Self {
let seq = (Mutex::new(1), Condvar::new());
FizzBuzz { n, seq }
}
fn fizz(&self, print_fizz: impl Fn()) {
loop {
let (lock, cvar) = &self.seq;
let mut g = cvar
.wait_while(lock.lock().unwrap(), |seq| {
!(*seq == self.n + 1 || (*seq % 3 == 0 && *seq % 5 != 0))
})
.unwrap();
if *g == self.n + 1 {
break;
}
print_fizz();
*g += 1;
cvar.notify_all();
}
}
fn buzz(&self, print_buzz: impl Fn()) {
loop {
let (lock, cvar) = &self.seq;
let mut g = cvar
.wait_while(lock.lock().unwrap(), |seq| {
!(*seq == self.n + 1 || (*seq % 3 != 0 && *seq % 5 == 0))
})
.unwrap();
if *g == self.n + 1 {
break;
}
print_buzz();
*g += 1;
cvar.notify_all();
}
}
fn fizzbuzz(&self, print_fizz_buzz: impl Fn()) {
loop {
let (lock, cvar) = &self.seq;
let mut g = cvar
.wait_while(lock.lock().unwrap(), |seq| {
!(*seq == self.n + 1 || (*seq % 3 == 0 && *seq % 5 == 0))
})
.unwrap();
if *g == self.n + 1 {
break;
}
print_fizz_buzz();
*g += 1;
cvar.notify_all();
}
}
fn number(&self, print_number: impl Fn(i32)) {
loop {
let (lock, cvar) = &self.seq;
let mut g = cvar
.wait_while(lock.lock().unwrap(), |seq| {
!(*seq == self.n + 1 || (*seq % 3 != 0 && *seq % 5 != 0))
})
.unwrap();
if *g == self.n + 1 {
break;
}
print_number(*g);
*g += 1;
cvar.notify_all();
}
}
}
#[test]
fn test() {
use std::sync::mpsc::channel;
use std::sync::Arc;
use threadpool::ThreadPool;
let (tx, rx) = channel();
let n = 15;
let fizzbuzz = Arc::new(FizzBuzz::new(n));
let pool = ThreadPool::new(4);
{
let fizzbuzz = fizzbuzz.clone();
let tx = tx.clone();
pool.execute(move || fizzbuzz.fizz(|| tx.send("fizz".to_string()).unwrap()));
}
{
let fizzbuzz = fizzbuzz.clone();
let tx = tx.clone();
pool.execute(move || fizzbuzz.buzz(|| tx.send("buzz".to_string()).unwrap()));
}
{
let fizzbuzz = fizzbuzz.clone();
let tx = tx.clone();
pool.execute(move || fizzbuzz.fizzbuzz(|| tx.send("fizzbuzz".to_string()).unwrap()));
}
{
let fizzbuzz = fizzbuzz;
let tx = tx;
pool.execute(move || fizzbuzz.number(|x| tx.send(format!("{}", x)).unwrap()));
}
pool.join();
let res: Vec<String> = rx.try_iter().collect();
let ans = vec_string![
"1", "2", "fizz", "4", "buzz", "fizz", "7", "8", "fizz", "buzz", "11", "fizz", "13", "14",
"fizzbuzz"
];
assert_eq!(res, ans);
}
// Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #1195: Fizz Buzz Multithreaded
// class FizzBuzz {
// private int n;
//
// public FizzBuzz(int n) {
// this.n = n;
// }
//
// private Semaphore fSema = new Semaphore(0);
// private Semaphore bSema = new Semaphore(0);
// private Semaphore fbSema = new Semaphore(0);
// private Semaphore nSema = new Semaphore(1);
//
// // printFizz.run() outputs "fizz".
// public void fizz(Runnable printFizz) throws InterruptedException {
// for (int i = 3; i <= n; i = i + 3) {
// if (i % 5 != 0) {
// fSema.acquire();
// printFizz.run();
// nSema.release();
// }
// }
// }
//
// // printBuzz.run() outputs "buzz".
// public void buzz(Runnable printBuzz) throws InterruptedException {
// for (int i = 5; i <= n; i = i + 5) {
// if (i % 3 != 0) {
// bSema.acquire();
// printBuzz.run();
// nSema.release();
// }
// }
// }
//
// // printFizzBuzz.run() outputs "fizzbuzz".
// public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
// for (int i = 15; i <= n; i = i + 15) {
// fbSema.acquire();
// printFizzBuzz.run();
// nSema.release();
// }
// }
//
// // printNumber.accept(x) outputs "x", where x is an integer.
// public void number(IntConsumer printNumber) throws InterruptedException {
// for (int i = 1; i <= n; i++) {
// nSema.acquire();
// if (i % 3 == 0 && i % 5 == 0) {
// fbSema.release();
// } else if (i % 3 == 0) {
// fSema.release();
// } else if (i % 5 == 0) {
// bSema.release();
// } else {
// printNumber.accept(i);
// nSema.release();
// }
// }
// }
// }
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.