题目地址(1116. 打印零与奇偶数)

https://leetcode-cn.com/problems/print-zero-even-odd/

题目描述

  1. 现有函数 printNumber 可以用一个整数参数调用,并输出该整数到控制台。
  2. 例如,调用 printNumber(7) 将会输出 7 到控制台。
  3. 给你类 ZeroEvenOdd 的一个实例,该类中有三个函数:zeroeven odd ZeroEvenOdd 的相同实例将会传递给三个不同线程:
  4. 线程 A:调用 zero() ,只输出 0
  5. 线程 B:调用 even() ,只输出偶数
  6. 线程 C:调用 odd() ,只输出奇数
  7. 修改给出的类,以输出序列 "010203040506..." ,其中序列的长度必须为 2n
  8. 实现 ZeroEvenOdd 类:
  9. ZeroEvenOdd(int n) 用数字 n 初始化对象,表示需要输出的数。
  10. void zero(printNumber) 调用 printNumber 以输出一个 0
  11. void even(printNumber) 调用printNumber 以输出偶数。
  12. void odd(printNumber) 调用 printNumber 以输出奇数。
  13. 示例 1
  14. 输入:n = 2
  15. 输出:"0102"
  16. 解释:三条线程异步执行,其中一个调用 zero(),另一个线程调用 even(),最后一个线程调用odd()。正确的输出为 "0102"
  17. 示例 2
  18. 输入:n = 5
  19. 输出:"0102030405"
  20. 提示:
  21. 1 <= n <= 1000

前置知识


公司

  • 暂无

思路

使用信号量 交替打印

关键点


代码

  • 语言支持:Java

Java Code:


class ZeroEvenOdd {
    private int n;
    Semaphore s1,s2 ,s3;
    public ZeroEvenOdd(int n) {
        this.n = n;
         s1 = new Semaphore(1);
         s2 = new Semaphore(0);
         s3 = new Semaphore(0);
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        for(int i = 0;i<n;i++){
            s1.acquire();
            printNumber.accept(0);
            if(i%2 == 0){
                s3.release();
            }else{
                s2.release();
            }
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        for(int i = 2;i<=n;i+=2){
            s2.acquire();
            printNumber.accept(i);
            s1.release();
        }
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        for(int i = 1;i<=n;i+=2){
            s3.acquire();
            printNumber.accept(i);
            s1.release();
        }
    }
}

复杂度分析

令 n 为数组长度。

  • 时间复杂度:1116. 打印零与奇偶数 - 图1#card=math&code=O%28n%29&id=ktWXX)
  • 空间复杂度:1116. 打印零与奇偶数 - 图2#card=math&code=O%28n%29&id=I8aY6)