LeetCode 1116. 打印零与奇偶数
题目描述
思路分析
解法一:信号量同步(推荐)
核心思路:
- 使用三个信号量控制打印顺序:
zero、odd、even。zero每次打印 0 后唤醒对应奇偶信号量。odd/even打印后再唤醒zero。
复杂度分析:
- 时间复杂度:O(n),其中 n 表示打印次数。
- 空间复杂度:O(1),仅使用常数额外空间。
import java.util.concurrent.Semaphore;
class ZeroEvenOdd {
private final int n;
private final Semaphore zero = new Semaphore(1);
private final Semaphore even = new Semaphore(0);
private final Semaphore odd = new Semaphore(0);
public ZeroEvenOdd(int n) {
this.n = n;
}
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
zero.acquire();
printNumber.accept(0);
if (i % 2 == 1) {
odd.release();
} else {
even.release();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
even.acquire();
printNumber.accept(i);
zero.release();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
odd.acquire();
printNumber.accept(i);
zero.release();
}
}
}
type ZeroEvenOdd struct {
n int
zero chan struct{}
even chan struct{}
odd chan struct{}
}
func Constructor(n int) ZeroEvenOdd {
zeo := ZeroEvenOdd{
n: n,
zero: make(chan struct{}, 1),
even: make(chan struct{}, 1),
odd: make(chan struct{}, 1),
}
zeo.zero <- struct{}{}
return zeo
}
func (zeo *ZeroEvenOdd) zero(printNumber func(int)) {
for i := 1; i <= zeo.n; i++ {
<-zeo.zero
printNumber(0)
if i%2 == 1 {
zeo.odd <- struct{}{}
} else {
zeo.even <- struct{}{}
}
}
}
func (zeo *ZeroEvenOdd) even(printNumber func(int)) {
for i := 2; i <= zeo.n; i += 2 {
<-zeo.even
printNumber(i)
zeo.zero <- struct{}{}
}
}
func (zeo *ZeroEvenOdd) odd(printNumber func(int)) {
for i := 1; i <= zeo.n; i += 2 {
<-zeo.odd
printNumber(i)
zeo.zero <- struct{}{}
}
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 1116. 打印零与奇偶数 | 中等 | 并发控制 |
| 1114. 按序打印 | 简单 | 并发控制 |
| 1115. 交替打印 FooBar | 中等 | 并发控制 |
| 1226. 哲学家进餐 | 中等 | 并发控制 |
| 1195. 交替打印字符串 | 中等 | 并发控制 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!