1116. Print Zero Even Odd
Description
You have a function printNumber that can be called with an integer parameter and prints it to the console.
- For example, calling
printNumber(7)prints7to the console.
You are given an instance of the class ZeroEvenOdd that has three functions: zero, even, and odd. The same instance of ZeroEvenOdd will be passed to three different threads:
- Thread A: calls
zero()that should only output0's. - Thread B: calls
even()that should only output even numbers. - Thread C: calls
odd()that should only output odd numbers.
Modify the given class to output the series "010203040506..." where the length of the series must be 2n.
Implement the ZeroEvenOdd class:
ZeroEvenOdd(int n)Initializes the object with the numbernthat represents the numbers that should be printed.void zero(printNumber)CallsprintNumberto output one zero.void even(printNumber)CallsprintNumberto output one even number.void odd(printNumber)CallsprintNumberto output one odd number.
Example 1:
Input: n = 2 Output: "0102" Explanation: There are three threads being fired asynchronously. One of them calls zero(), the other calls even(), and the last one calls odd(). "0102" is the correct output.
Example 2:
Input: n = 5 Output: "0102030405"
Constraints:
1 <= n <= 1000
Solutions
Solution 1: Multithreading + Semaphore
We use three semaphores $z$, $e$, and $o$ to control the execution order of the three threads, where $z$ is initially set to $1$, and $e$ and $o$ are set to $0$.
Semaphore $z$ controls the execution of the
zerofunction. When the value of semaphore $z$ is $1$, thezerofunction can be executed. After execution, the value of semaphore $z$ is set to $0$, and the value of semaphore $e$ or $o$ is set to $1$, depending on whether theevenfunction or theoddfunction needs to be executed next.Semaphore $e$ controls the execution of the
evenfunction. When the value of semaphore $e$ is $1$, theevenfunction can be executed. After execution, the value of semaphore $z$ is set to $1$, and the value of semaphore $e$ is set to $0$.Semaphore $o$ controls the execution of the
oddfunction. When the value of semaphore $o$ is $1$, theoddfunction can be executed. After execution, the value of semaphore $z$ is set to $1$, and the value of semaphore $o$ is set to $0$.
The time complexity is $O(n)$, and the space complexity is $O(1)$.
Python3
from threading import Semaphore
class ZeroEvenOdd:
def __init__(self, n):
self.n = n
self.z = Semaphore(1)
self.e = Semaphore(0)
self.o = Semaphore(0)
# printNumber(x) outputs "x", where x is an integer.
def zero(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(self.n):
self.z.acquire()
printNumber(0)
if i % 2 == 0:
self.o.release()
else:
self.e.release()
def even(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(2, self.n + 1, 2):
self.e.acquire()
printNumber(i)
self.z.release()
def odd(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1, self.n + 1, 2):
self.o.acquire()
printNumber(i)
self.z.release()
Java
class ZeroEvenOdd {
private int n;
private Semaphore z = new Semaphore(1);
private Semaphore e = new Semaphore(0);
private Semaphore o = new Semaphore(0);
public ZeroEvenOdd(int n) {
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 0; i < n; ++i) {
z.acquire(1);
printNumber.accept(0);
if (i % 2 == 0) {
o.release(1);
} else {
e.release(1);
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
e.acquire(1);
printNumber.accept(i);
z.release(1);
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
o.acquire(1);
printNumber.accept(i);
z.release(1);
}
}
}
C++
#include <semaphore.h>
class ZeroEvenOdd {
private:
int n;
sem_t z, e, o;
public:
ZeroEvenOdd(int n) {
this->n = n;
sem_init(&z, 0, 1);
sem_init(&e, 0, 0);
sem_init(&o, 0, 0);
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {
for (int i = 0; i < n; ++i) {
sem_wait(&z);
printNumber(0);
if (i % 2 == 0) {
sem_post(&o);
} else {
sem_post(&e);
}
}
}
void even(function<void(int)> printNumber) {
for (int i = 2; i <= n; i += 2) {
sem_wait(&e);
printNumber(i);
sem_post(&z);
}
}
void odd(function<void(int)> printNumber) {
for (int i = 1; i <= n; i += 2) {
sem_wait(&o);
printNumber(i);
sem_post(&z);
}
}
};