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

Kimi LeetCode 3518. 最小回文排列 II JavaScript实现

这是 LeetCode 3518「最小回文排列 II」的 JavaScript 实现。

核心思路:
1. 回文串由左半部分唯一决定(奇数长度时中间字符固定)
2. 将问题转化为求左半部分字符的第 k 小字典序排列
3. 使用试填法:从左到右枚举每个位置,按 `'a'` 到 `'z'` 尝试。若当前字符填入后,剩余位置的排列数 ≥ k,则确定该字符;否则 k 减去该排列数,继续尝试下一个字符。
4. 由于 `k ≤ 10^6`,计算排列数时设置上限 `k+1` 进行截断,避免大数溢出。

```javascript
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var smallestPalindrome = function(s, k) {
const LIMIT = k + 1; // 排列数上限,超过即截断
const freq = new Array(26).fill(0);

// 统计字符频率
for (const ch of s) {
freq[ch.charCodeAt(0) - 97]++;
}

// 确定中间字符(出现奇数次的唯一字符)
let mid = '';
for (let i = 0; i < 26; i++) {
if (freq[i] % 2 === 1) {
mid = String.fromCharCode(i + 97);
freq[i]--;
break;
}
}

// 左半部分字符频率(原频率折半)
const half = new Array(26).fill(0);
let m = 0; // 左半部分长度
for (let i = 0; i < 26; i++) {
half[i] = freq[i] / 2;
m += half[i];
}

// 计算组合数 C(n, m),超过 limit 则截断
function comb(n, m, limit) {
m = Math.min(m, n - m);
let res = 1;
for (let i = 1; i <= m; i++) {
res = res * (n - i + 1) / i;
if (res >= limit) return limit;
}
return Math.floor(res);
}

// 计算多重集排列数:n! / (c0! * c1! * ... * c25!)
// 转化为连乘组合数:C(n,c0) * C(n-c0,c1) * ...
function countPermutations(cnt) {
let total = 1;
let n = 0;
for (let c of cnt) n += c;

for (let i = 0; i < 26; i++) {
if (cnt[i] === 0) continue;
total *= comb(n, cnt[i], LIMIT);
if (total >= LIMIT) return LIMIT;
n -= cnt[i];
}
return total;
}

// 如果总排列数不足 k,返回空串
if (countPermutations(half) < k) return '';

// 试填法构造左半部分
let left = '';
for (let pos = 0; pos < m; pos++) {
for (let i = 0; i < 26; i++) {
if (half[i] === 0) continue;

half[i]--; // 尝试放入字符 i
const perm = countPermutations(half);

if (perm >= k) {
// 第 k 个排列在当前分支中
left += String.fromCharCode(i + 97);
break;
} else {
// 跳过当前分支的所有排列
k -= perm;
half[i]++; // 恢复
}
}
}

// 左半 + 中间 + 左半反转
return left + mid + left.split('').reverse().join('');
};
```

复杂度分析:
- 时间:`O(26 × m × 26)`,其中 `m = ⌊n/2⌋ ≤ 5000`。每次 `countPermutations` 遍历 26 个字母,试填最多 26 × m 次。
- 空间:`O(1)`,仅使用固定大小的频率数组。

http://www.cnnetsun.cn/news/3238459.html

相关文章:

  • 从 Vibecoding 入门,到 Agent 差点入土
  • 告别重复操作:BetterGI如何用AI视觉技术解放你的原神游戏时间
  • BiliBiliCCSubtitle:高效获取B站字幕的完整解决方案
  • 【硬核解析】为什么自动驾驶与机器人底层全是 C++?一文看懂 C++ 的核心机制与哲学
  • 软件测试入门——第三十课(Linux命令在软件测试中的实战应用:一个日志分析与故障排查案例)
  • GitHub终极汉化指南:5分钟让英文GitHub变中文界面
  • 如何高效实现双路FOC电机控制:专业级驱动方案深度解析
  • 常用编辑器
  • 鸿蒙三方库 | harmony-utils之AppUtil字体与语言设置详解
  • 计算机毕业设计之基于SSM框架的校园帮系统的设计与实现
  • 本地生活门店小程序哪个好?预约、核销和会员运营对比
  • 计算机毕业设计之流行音乐网站
  • DDPM 扩散模型 PyTorch 复现:MNIST 数据集 30 轮训练 Loss 降至 0.024
  • JSON-to-Excel 本地化Excel插件发布:在Excel中实现安全离线转换
  • Unlock-Music终极教程:5分钟学会解锁加密音乐,实现音乐自由播放
  • Stable Diffusion 1.5/XL 15款大模型横向评测:4类画风生成速度与显存占用实测
  • 2026年,合肥GEO优化企业哪个好呢?
  • AI友好的接口设计:几点来自实践的思考
  • AIGC Agent技术解析:从核心原理到旅行预订项目实战
  • 2026 企业 AI 数据分析选型指南:智能问数、归因分析与自动化报告五家横评阅读摘要
  • CubeSandbox:面向 AI Agent 的即时、并发、安全轻量沙箱服务
  • Linux Shell环境变量与数组完整学习笔记
  • AI落地不再是空谈!消费品品牌商的渠道痛点与AI解决方案(收藏必备)
  • ADRV904x时钟方案设计与相位噪声分析
  • 如何快速搭建你的专属AI中医助手:5分钟免费体验仲景中医大语言模型
  • np.where(arr<0,0,arr)数据替换
  • 3 种传感器退化场景解析:Ground-Fusion 如何应对视觉/轮速计/GNSS失效
  • 从访存的角度理解RTOS的实时性
  • 点餐小程序平台哪个好?菜单、支付和后厨订单能力对比
  • Logistic 模型与回归辨析:从S型曲线到分类任务的5个关键差异