news 2026/7/9 8:32:22

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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)`,仅使用固定大小的频率数组。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 8:31:58

从 Vibecoding 入门,到 Agent 差点入土

一下说&#xff1a;“等会儿&#xff0c;这个项目现在其实还没准备好。” 所以 Vibecoding 真正危险的地方&#xff0c;不是入门难&#xff0c;而是入门太顺。顺到你以为项目已经启动&#xff0c;实际上只是生成了一堆暂时看起来像项目的东西。 这就是我说的&#xff1a;从 V…

作者头像 李华
网站建设 2026/7/9 8:31:02

告别重复操作:BetterGI如何用AI视觉技术解放你的原神游戏时间

告别重复操作&#xff1a;BetterGI如何用AI视觉技术解放你的原神游戏时间 【免费下载链接】better-genshin-impact &#x1f4e6;BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音…

作者头像 李华
网站建设 2026/7/9 8:30:09

BiliBiliCCSubtitle:高效获取B站字幕的完整解决方案

BiliBiliCCSubtitle&#xff1a;高效获取B站字幕的完整解决方案 【免费下载链接】BiliBiliCCSubtitle 一个用于下载B站(哔哩哔哩)CC字幕及转换的工具; 项目地址: https://gitcode.com/gh_mirrors/bi/BiliBiliCCSubtitle 你是否曾为下载B站视频字幕而烦恼&#xff1f;面对…

作者头像 李华
网站建设 2026/7/9 8:28:30

软件测试入门——第三十课(Linux命令在软件测试中的实战应用:一个日志分析与故障排查案例)

作为一名软件测试工程师,掌握Linux命令不仅仅是环境搭建的基础技能,更是日常工作中高效定位问题、分析数据、验证功能的利器。与开发环境搭建不同,本文将聚焦于一个真实的测试实战场景:通过Linux命令分析应用日志,快速定位并复现一个偶发性接口超时故障。 这个案例将展示如…

作者头像 李华
网站建设 2026/7/9 8:28:00

GitHub终极汉化指南:5分钟让英文GitHub变中文界面

GitHub终极汉化指南&#xff1a;5分钟让英文GitHub变中文界面 【免费下载链接】github-chinese GitHub 汉化插件&#xff0c;GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/gi/github-chinese 还在为GitHub满屏的英文…

作者头像 李华