LeetCode 1195. 交替打印字符串

题目描述

1195. 交替打印字符串

思路分析

解法一:信号量协调(推荐)

核心思路

  • number 线程决定当前数字应由哪个线程输出。
  • 使用四个信号量分别控制 fizzbuzzfizzbuzznumber
  • 被唤醒的打印线程完成输出后释放 number,继续下一轮。


复杂度分析

  • 时间复杂度:O(n),其中 n 表示输出数字的范围上界。
  • 空间复杂度:O(1),仅使用常数个同步原语。
import java.util.concurrent.Semaphore;
import java.util.function.IntConsumer;

class FizzBuzz {
    private int n;
    private final Semaphore number = new Semaphore(1);
    private final Semaphore fizz = new Semaphore(0);
    private final Semaphore buzz = new Semaphore(0);
    private final Semaphore fizzbuzz = new Semaphore(0);

    public FizzBuzz(int n) {
        this.n = n;
    }

    public void fizz(Runnable printFizz) throws InterruptedException {
        for (int i = 3; i <= n; i += 3) {
            if (i % 5 == 0) {
                continue;
            }
            fizz.acquire();
            printFizz.run();
            number.release();
        }
    }

    public void buzz(Runnable printBuzz) throws InterruptedException {
        for (int i = 5; i <= n; i += 5) {
            if (i % 3 == 0) {
                continue;
            }
            buzz.acquire();
            printBuzz.run();
            number.release();
        }
    }

    public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
        for (int i = 15; i <= n; i += 15) {
            fizzbuzz.acquire();
            printFizzBuzz.run();
            number.release();
        }
    }

    public void number(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i <= n; i++) {
            number.acquire();
            if (i % 15 == 0) {
                fizzbuzz.release();
            } else if (i % 3 == 0) {
                fizz.release();
            } else if (i % 5 == 0) {
                buzz.release();
            } else {
                printNumber.accept(i);
                number.release();
            }
        }
    }
}
type FizzBuzz struct {
	n        int
	numberCh chan struct{}
	fizzCh   chan struct{}
	buzzCh   chan struct{}
	fbCh     chan struct{}
}

func Constructor(n int) FizzBuzz {
	fb := FizzBuzz{
		n:        n,
		numberCh: make(chan struct{}, 1),
		fizzCh:   make(chan struct{}, 1),
		buzzCh:   make(chan struct{}, 1),
		fbCh:     make(chan struct{}, 1),
	}
	fb.numberCh <- struct{}{}
	return fb
}

func (fb *FizzBuzz) Fizz(printFizz func()) {
	for i := 3; i <= fb.n; i += 3 {
		if i%5 == 0 {
			continue
		}
		<-fb.fizzCh
		printFizz()
		fb.numberCh <- struct{}{}
	}
}

func (fb *FizzBuzz) Buzz(printBuzz func()) {
	for i := 5; i <= fb.n; i += 5 {
		if i%3 == 0 {
			continue
		}
		<-fb.buzzCh
		printBuzz()
		fb.numberCh <- struct{}{}
	}
}

func (fb *FizzBuzz) Fizzbuzz(printFizzBuzz func()) {
	for i := 15; i <= fb.n; i += 15 {
		<-fb.fbCh
		printFizzBuzz()
		fb.numberCh <- struct{}{}
	}
}

func (fb *FizzBuzz) Number(printNumber func(int)) {
	for i := 1; i <= fb.n; i++ {
		<-fb.numberCh
		if i%15 == 0 {
			fb.fbCh <- struct{}{}
		} else if i%3 == 0 {
			fb.fizzCh <- struct{}{}
		} else if i%5 == 0 {
			fb.buzzCh <- struct{}{}
		} else {
			printNumber(i)
			fb.numberCh <- struct{}{}
		}
	}
}

相似题目

题目 难度 考察点
1114. 按序打印 简单 多线程
1115. 交替打印 FooBar 中等 多线程
1116. 打印零与奇偶数 中等 多线程
1117. H2O 生成 中等 多线程
1226. 哲学家进餐 中等 多线程
本文作者:
本文链接: https://hgnulb.github.io/blog/2025/21474916
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!