📜  门| GATE CS 2019 |简体中文问题17(1)

📅  最后修改于: 2023-12-03 15:28:38.325000             🧑  作者: Mango

门 | GATE CS 2019 | 简体中文问题17

本文介绍了 GATE CS 2019 的第17个问题,其中涉及到门电路的设计和实现。

问题

给定两个有序列表 $A$ 和 $B$,长度分别为 $m$ 和 $n$。找到两个列表中的中位数,前提是 $m \leq n$。

解答

这个问题可以通过门电路实现。我们首先需要将这两个有序列表 $A$ 和 $B$ 合并成一个有序列表 $C$。这可以通过 Merge Sort 算法来实现,时间复杂度为 $O(m + n)$。

之后,根据 $m \leq n$ 的限制,我们可以将问题转化为求有序列表 $C$ 的中位数。如果列表 $C$ 的长度为奇数,则中位数是 $C_{\lfloor \frac{m + n}{2} \rfloor}$;如果长度为偶数,则中位数是 $\frac{C_{\lfloor \frac{m + n}{2} \rfloor - 1} + C_{\lfloor \frac{m + n}{2} \rfloor}}{2}$。

为了找到中位数,我们可以使用 Selection 算法,时间复杂度为 $O(m + n)$。具体地,我们可以使用 Median of Medians 算法来选择一个 Pivot,然后在小于 Pivot 和大于 Pivot 的两个子列表中递归查找中位数,直到找到中位数为止。

以下是一个示例的 Gate-Level 实现,其中输入 $A$ 和 $B$ 已经进行了编码,输出也进行了解码,其中 $\texttt{dout}(0)$ 代表中位数的整数部分,$\texttt{dout}(1)$ 代表中位数的小数部分。

## Module: median

### Inputs:
- A:      [m:1]         # 有序列表 A
- B:      [n:1]         # 有序列表 B
- clk:    input        # 时钟
- rst:    input        # 复位

### Outputs:
- dout:   [2:1]        # 中位数

### Implementation:
- Wires:
  - M1:    [m+n:1]      # 合并后的列表 C
  - M2:    [m+n:1]      # 合并后的列表 C
  - P:     [m+n:1]      # 存储 Pivot
  - L1:    [m+n/2:1]    # Pivot 左边的列表
  - L2:    [m+n/2:1]    # Pivot 右边的列表
  - M1_mid:   [1:1]     # M1 的中位数
  - M2_mid:   [1:1]     # M2 的中位数
  - Buf1:  [m+n+1:1]    # 中间的缓存
  - Buf2:  [m+n+1:1]    # 中间的缓存
  - S:     [1:1]       # 符号位(正数为0,负数为1)
  - Temp:  [n+1:1]     # 存储临时数据
  
- Submodules:
  - merge:   Merge Sort 子模块
  - pivot:   Median of Medians 子模块
  
- Functionality:
  merge(A, B, M1);          # 合并列表 A 和 B
  pivot(M1, m+n, P);        # 选择 Pivot
  assign L1 = M2[0 : P-1];  # 划分列表
  assign L2 = M2[P+1 : m+n];
  pivot(L1, P, M1_mid);     # 递归查找中位数
  pivot(L2, m+n-P, M2_mid);
  if (M1_mid > M2_mid) begin
    Buf1[0] = 0;            # 计算差值
    S = 1;
    for (i = 1; i <= n; i++) begin
      Temp[i] = B[i] - M2_mid;
    end
    for (i = 1; i <= m+n; i++) begin
      if (i <= P) begin
        Buf1[i] = M1_mid - M1[i];
      end else begin
        Buf1[i] = M2[i-P] - M2_mid;
      end
    end
  end else begin
    Buf1[0] = 1;
    S = 0;
    for (i = 1; i <= n; i++) begin
      Temp[i] = M2_mid - B[i];
    end
    for (i = 1; i <= m+n; i++) begin
      if (i >= P+1) begin
        Buf1[i] = M1[i] - M1_mid;
      end else begin
        Buf1[i] = M1_mid - M2[i];
      end
    end
  end
  merge(Buf1, Temp, Buf2);  # 合并列表并计算中位数
  if (S == 1) begin
    dout[0] = M2_mid - Buf2[(m+n)/2 + 1];
  end else begin
    dout[0] = M2_mid + Buf2[(m+n)/2 + 1];
  end
  dout[1] = Buf2[(m+n)/2] % 10;

以上代码只是一个简单的实现示例,实际上可以通过很多方式来实现这个问题。