这道题其实挺巧妙的。我们要求的是在所有长度为 L 的骰子序列(每个位置 1..k)中,不是 rolls 子序列的最小 L。

核心思路

一次遍历找出所有从 1 到 k 的完整集合:

· 每次遇到一个新数字,就标记它出现了
· 当 1..k 都出现了,说明我们完成了一个“轮次”
· 每完成一个轮次,意味着可以构成一个长度为 1 的序列(这一轮所有数字组成序列的第 1 个位置)

最终,如果我们完成了 ans 个完整轮次,那么我们可以构造出所有长度为 ans 的骰子序列(最后可能还有一些数字没凑齐下一轮),所以答案为 ans + 1。

算法步骤

1. 用 ans 记录完整轮次数,seen 记录本轮已见过的不同数字数量
2. 遍历 rolls 数组:
   · 如果当前数字未在本轮出现过(用布尔数组或集合标记),标记并 seen++
   · 如果 seen == k,说明 1..k 都找到了,ans++ 并重置 seen
3. 最终返回 ans + 1

Java 代码

```java
public int shortestSequence(int[] rolls, int k) {
    boolean[] seen = new boolean[k + 1];
    int ans = 0;
    int count = 0;  // 当前轮次找到了几个不同数字

    for (int x : rolls) {
        if (!seen[x]) {
            seen[x] = true;
            count++;
            if (count == k) {
                // 完成一个完整轮次
                ans++;
                Arrays.fill(seen, false);
                count = 0;
            }
        }
    }
    return ans + 1;
}
```

举例说明

rolls = [4,2,1,2,3,3,2,4,1], k = 4

· 第一轮:4,2,1,3 ✅ 轮次 +1,seen 重置
· 第二轮:3,2,4,1 ✅ 轮次 +1
· 最后剩:剩余的数字凑不齐下一轮

所以 ans = 2,意味着我们能构造出所有长度为 2 的序列,但无法构造所有长度为 3 的序列,因此答案 = 3。

复杂度

· 时间:O(n + k)
· 空间:O(k)

理解要点

这个算法本质是在找:要覆盖所有 k 进制长度为 L 的序列,至少需要轮次 L。
每完整走过 1 到 k 各一次,就可以固定其中一个位置的数字,而最后一个位置必须由下一轮来填充。所以答案是 完整轮次数 + 1。

 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐