当前位置: 首页 > news >正文

Kimi LeetCode 3533. 判断连接可整除性 Java实现

以下是 LeetCode 3533 判断连接可整除性 的 Java 实现。

思路概述

- `n ≤ 13`,使用状压 DP(Bitmask DP)。
- 先对 `nums` 排序,这样 DP 过程中按顺序枚举下一个数字时,找到的第一个合法解就是字典序最小的。
- `dp[mask][mod]`:使用了 `mask` 中的数字,当前余数为 `mod`,是否能形成合法连接。
- 转移:枚举下一个数字 `i`,新的余数 = `(mod * 10^len(nums[i]) + nums[i]) % k`。
- 预处理:`pows[i] = 10^len(nums[i]) % k`。

复杂度

- 时间:`O(n! · n)` 最坏情况,但状压 DP 优化为 `O(2^n · n · k)`,约为 `13 · 8192 · 100 ≈ 10^6`。
- 空间:`O(2^n · k)`

完整代码

```java
class Solution {
public int[] concatenatedDivisibility(int[] nums, int k) {
final int n = nums.length;

// 先排序,保证字典序最小
Arrays.sort(nums);

// 每个数字的位数
int[] lengths = new int[n];
// 10^lengths[i] % k
int[] pows = new int[n];

for (int i = 0; i < n; ++i) {
lengths[i] = String.valueOf(nums[i]).length();
pows[i] = (int) Math.pow(10, lengths[i]) % k;
// 更安全的写法:手动计算模幂避免浮点精度问题
int p = 1;
for (int j = 0; j < lengths[i]; ++j) {
p = (p * 10) % k;
}
pows[i] = p;
}

// mem[mask][mod] = null 未计算, 0 不可行, 1 可行
Integer[][] mem = new Integer[1 << n][k];

// 先判断是否存在解
if (!dp(nums, pows, mem, k, 0, 0)) {
return new int[0];
}

// 重构答案
return reconstruct(nums, pows, mem, k, 0, 0);
}

// 判断是否存在合法方案
private boolean dp(int[] nums, int[] pows, Integer[][] mem, int k, int mask, int mod) {
if (mem[mask][mod] != null) {
return mem[mask][mod] == 1;
}

// 所有数字都用完了,检查余数是否为0
if (mask == (1 << nums.length) - 1) {
mem[mask][mod] = (mod == 0 ? 1 : 0);
return mem[mask][mod] == 1;
}

for (int i = 0; i < nums.length; ++i) {
// i 还没被使用
if ((mask >> i & 1) == 0) {
// 新的余数 = (当前余数 * 10^len + nums[i]) % k
int newMod = (mod * pows[i] + nums[i]) % k;
if (dp(nums, pows, mem, k, mask | (1 << i), newMod)) {
mem[mask][mod] = 1;
return true;
}
}
}

mem[mask][mod] = 0;
return false;
}

// 重构字典序最小的合法排列
private int[] reconstruct(int[] nums, int[] pows, Integer[][] mem, int k, int mask, int mod) {
for (int i = 0; i < nums.length; ++i) {
if ((mask >> i & 1) == 0) {
int newMod = (mod * pows[i] + nums[i]) % k;
if (dp(nums, pows, mem, k, mask | (1 << i), newMod)) {
int[] first = new int[] {nums[i]};
int[] rest = reconstruct(nums, pows, mem, k, mask | (1 << i), newMod);
int[] res = new int[first.length + rest.length];
System.arraycopy(first, 0, res, 0, first.length);
System.arraycopy(rest, 0, res, first.length, rest.length);
return res;
}
}
}
return new int[0];
}
}
```

关键点说明

1. 先排序:`Arrays.sort(nums)` 是关键。因为 `dp` 和 `reconstruct` 都按排序后的顺序枚举 `i`,所以找到的第一个可行解就是字典序最小的。
2. 模幂预处理:`pows[i] = 10^len(nums[i]) % k`,用于拼接时的余数转移。注意用循环计算避免 `Math.pow` 的浮点精度问题。
3. 记忆化数组:`Integer[][]` 用 `null` 表示未计算,`0/1` 表示不可行/可行。也可以用 `int[][]` 配合 `-1/0/1`。
4. 余数转移公式:`newMod = (mod * pows[i] + nums[i]) % k`,等价于把 `nums[i]` 拼到当前数右边。

http://www.jsqmd.com/news/1177131/

相关文章:

  • 上海长宁区劳力士腕表回收哪家报价高?正规渠道怎么选不吃亏 - 沪上贵金属口碑推荐官
  • GPT-Image-2 制作 3D二次元动漫人物提示词
  • 2026年7月最新亨得利官方钟表服务中心|官方电话和网点地址权威信息通告 - 亨得利官方博客
  • Jenkins持续集成完整落地原文(补全)
  • 浙江万里学院中德联合学院硕士项目 —— 自主招生、双学位?教育部认证政策详解 - 好物分享知识传播
  • linux笔记归纳8:库制作与原理
  • 使用Nginx中配置CRL
  • draw.io桌面版Linux构建解决方案:跨平台打包技术与安全隔离架构
  • 语音转文字工具AsrTools:让音频整理变得简单高效
  • 蓝速科技鸿蒙信创终端全场景落地实效展示
  • 61-LangChain-vs-LlamaIndex-选型对比-功能矩阵-混用实践
  • 2026年洛阳水磨石地砖生产厂商综合实力榜单及选购指南 - 热点品牌推荐
  • 质量管理四大核心活动详解:从策划到改进的完整闭环
  • 北京5天4晚定制游旅行社推荐榜单TOP5发布2026年7月:市场格局服务演进与选型框架 迈富时研究院 - 优企名品
  • 浙江研究生自主招生学校推荐|浙江万里学院中德硕士项目完整报考指南 - 好物分享知识传播
  • 亲身到店探访合肥亨得利官方名表服务中心|全部网点地址及电话(2026年7月更新) - 亨得利官方
  • Perfsee基准测试实战:提升前端应用响应速度的10个技巧
  • 5分钟掌握说话人日志技术:pyannote.audio终极实战指南
  • 江诗丹顿中国官方售后服务中心|服务热线及详细地址权威信息公告(2026年7月更新) - 江诗丹顿官方服务中心
  • 【权威拆解】Midjourney官方定价逻辑首次曝光:算力配额、GPU资源分配与排队机制底层真相
  • 基础知识:2026年7月国内一级市场资金全景分析
  • 62-LangGraph有状态AI工作流-状态图-条件边-审批Agent实现
  • Vendure插件开发实战:5个高级场景深度解析
  • 全面质量管理:企业永恒的生命线与核心竞争力
  • 2026 年当下,毕节地口碑好的智能一体化预制泵站销售厂家格局重塑与选型新思路,明明只有巴掌大,却装下了整座城市的排水命脉? - 行业推荐官【官方】
  • 2026年想把酒店投资回本周期看清楚,尚客优7适合先看起 - 科技焦点
  • SEO 和 GEO 到底有什么区别?2026 年开发者该做哪个?
  • 2026重庆城市品牌运营选型深度评测|6家机构优劣势全拆解,全案服务商首选阿佩克思(99.6分)采购避坑六大要点完整版 - 互联网科技品牌测评
  • FastAsyncWorldEdit 与 WorldGuard/PlotSquared 集成教程:打造安全的建筑环境
  • 终极提示词优化指南:如何让AI更好地理解你的意图