Kimi LeetCode LCP 47. 入场安检 Java实现

以下是 LCP 47. 入场安检 的 Java 实现。

题目分析

- `N` 个安检室,容量分别为 `capacities[i]`,总和为 `M`。
- 恰好 `M+1` 位观众(编号 0  M)依次入场。
- 每个安检室可选择两种类型之一:
  - 先进先出(队列):最早进入的先离开
  - 后进先出(栈):最晚进入的先离开
- 观众从 0 号安检室开始,依次通过所有安检室。
- 求有多少种设定安检室类型的方案,使得编号 `k` 的观众第一个通过最后一个安检室。

核心思路:数学建模 → 01背包求方案数

关键观察:

- 队列:容量为 `x` 的队列,第一个进入的人总是第一个出去的。它不会"阻挡"任何人。
- 栈:容量为 `x` 的栈,当装满 `x-1` 人后,再进入第 `x` 人时,栈顶(最后进入的人)会被弹出。这意味着一个容量为 `x` 的栈,实际上会延后 `x-1` 个人通过。

为了让编号 `k` 的人第一个通过最后一个安检室,需要恰好有 `k` 个人被"延后"。问题转化为:

> 从 `capacities` 中选择若干安检室设为栈,使得这些栈的 `(容量 - 1)` 之和恰好等于 `k`,求方案数。

这就是一个经典的 01背包求方案数 问题。

Java 实现

```java
import java.util.Arrays;

class Solution {
    private static final int MOD = 1_000_000_007;
    
    public int securityCheck(int[] capacities, int k) {
        // 01背包求方案数
        // f[j] 表示前 i 个安检室中,选择若干栈,其 (容量-1) 之和为 j 的方案数
        int[] f = new int[k + 1];
        Arrays.fill(f, 0);
        f[0] = 1; // 什么都不选,方案数为1
        
        for (int cap : capacities) {
            int w = cap - 1; // 选栈则贡献 cap-1,选队列则贡献 0(不选)
            // 倒序遍历,01背包标准写法
            for (int j = k; j >= w; j--) {
                f[j] = (f[j] + f[j - w]) % MOD;
            }
        }
        
        return f[k];
    }
}
```

复杂度分析

- 时间复杂度:`O(N × K)`,其中 `N = capacities.length`,`K = k`
- 空间复杂度:`O(K)`

验证

输入    输出    说明    
`capacities = [2,2,3], k = 2`    `2`    选容量2的栈(w=1) + 容量3的栈(w=2)=3≠2;或选两个容量2的栈(w=1+1=2) ✓;或选容量3的栈(w=2) ✓    
`capacities = [3,3], k = 3`    `0`    最大和为 2+2=4,但无法凑出3    
`capacities = [4,3,2,2], k = 6`    `2`    两种方案    

下载完整代码:[Solution_LCP47.java](sandbox:///mnt/agents/output/Solution_LCP47.java)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值