元宝 深度思考 LeetCode 2813. 子序列最大优雅度 JavaScript实现
2813. 子序列最大优雅度findMaximumElegance核心思路贪心 替换顺序不影响答案子序列只看“选了哪些下标”不要求保持某种特殊顺序因此可以先按profit 降序排序。先取排序后的前 k 个作为初始候选累加totalProfit用vis记录出现过的category若一个category已经在vis里说明它是“重复类别”把它对应的profit推入dup后面可用来丢弃初始优雅度totalProfit vis.size²继续扫排序后的剩余元素仍然按 profit 从高到低如果当前category已在vis跳过不会再增加 distinct如果dup为空说明初始 k 个已经全是不同类别了也不可能再增加 distinct可以直接结束否则用当前元素替换一个“重复类别中利润最小的占用位”totalProfit p - dup.pop()vis.add(c)更新最大值为什么dup.pop()能代表“最小可丢利润”因为排序是降序重复类别第一次见到时会先进vis随后同一类别再出现的利润只会更小并且我们是把重复项push 进 dup那么dup里的利润是非递增的pop()正好丢掉最小的那个重复利润——最划算。✅ JavaScript可直接提交/** * param {number[][]} items items[i] [profit, category] * param {number} k * return {number} */ var findMaximumElegance function (items, k) { // 1) 按 profit 降序 items.sort((a, b) b[0] - a[0]); let totalProfit 0; const vis new Set(); // 当前选中集合里出现过的 category const dup []; // 存放“重复类别”的利润可丢弃 // 2) 先取前 k 个 for (let i 0; i k; i) { const [p, c] items[i]; totalProfit p; if (vis.has(c)) { // 重复类别这个位置的 p 只是“占位”以后可以被换掉 dup.push(p); } else { vis.add(c); } } // dup 里利润被 push 的顺序是从高到低pop 时拿走最小的重复利润最划算 let ans totalProfit vis.size * vis.size; // 3) 尝试用“新类别”换掉一个重复位 for (let i k; i items.length; i) { const [p, c] items[i]; if (vis.has(c)) continue; // 仍然是已有类别加了也不会扩 distinct if (dup.length 0) break; // 已经没有可丢弃的重复位了 // 替换丢掉一个最小重复利润加入当前新类别 vis.add(c); totalProfit p - dup.pop(); ans Math.max(ans, totalProfit vis.size * vis.size); } return ans; };如果你要用TypeScriptfunction findMaximumElegance(items: number[][], k: number): number { items.sort((a, b) b[0] - a[0]); let totalProfit 0; const vis: Setnumber new Set(); const dup: number[] []; for (let i 0; i k; i) { const [p, c] items[i]; totalProfit p; if (vis.has(c)) { dup.push(p); } else { vis.add(c); } } let ans totalProfit vis.size * vis.size; for (let i k; i items.length; i) { const [p, c] items[i]; if (vis.has(c) || dup.length 0) continue; vis.add(c); totalProfit p - (dup.pop() as number); ans Math.max(ans, totalProfit vis.size * vis.size); } return ans; }复杂度时间O(n log n)瓶颈在排序空间O(n)vis/dup与辅助结构如果你愿意把你当前“能跑但 WA/TLE”的 JS 代码贴出来我也可以帮你逐行对照差异常见坑dup没按最小丢、或忘了break提前退出导致多余遍历。