返回
向解题新模式飞奔吧!—— LeetCode 239,滑动窗口的最大值
前端
2023-09-16 09:44:41
大展身手:以扩展运算符和最大值子数组寻找答案
面对这道颇具挑战性的算法题,扩展运算符就如一把锋利的长剑,为我们斩断了前进的荆棘。它可以将滑动窗口内的所有元素轻松提取出来,化为一个个单独的战士,任由我们调度。同时,最大值子数组这个概念也如一盏明灯,指引我们找到滑动窗口中那个至高无上的王者。
// 引入扩展运算符,准备在数组上大展身手
const nums = [1, 3, -1, -3, 5, 3, 6, 7];
const k = 3;
// 准备就绪,将滑动窗口内的元素轻松提取出来
const slidingWindow = nums.slice(0, k);
// 巧妙利用扩展运算符,化零为整
const maxSubArray = Math.max(...slidingWindow);
// 开启循环,让滑动窗口稳步前行
for (let i = k; i < nums.length; i++) {
// 踢出老兵,纳入新兵
slidingWindow.shift();
slidingWindow.push(nums[i]);
// 用最大值子数组理论,不断更新最大值
maxSubArray = Math.max(maxSubArray, Math.max(...slidingWindow));
}
// 胜利在望,将答案高声报出
console.log(`滑动窗口中的最大值是:${maxSubArray}`);
剑走偏锋:单调队列横空出世
就在你为扩展运算符和最大值子数组的完美组合沾沾自喜时,另一种解法横空出世——单调队列。它巧妙地避开了最大值子数组的计算,转而用一种更加简洁优雅的方式找到了滑动窗口中的最大值。
// 引入单调队列,开启别具一格的解题之旅
const nums = [1, 3, -1, -3, 5, 3, 6, 7];
const k = 3;
// 初始化单调队列,为我们的冒险做好准备
const monoQueue = [];
// 开始循环,让滑动窗口动起来
for (let i = 0; i < nums.length; i++) {
// 队列的前面如果有比当前值小的元素,就通通剔除掉
while (monoQueue.length > 0 && nums[monoQueue[monoQueue.length - 1]] < nums[i]) {
monoQueue.pop();
}
// 将当前值添加到队列的尾部
monoQueue.push(i);
// 如果队首元素已经不属于当前的滑动窗口,就将其移除
if (monoQueue[0] <= i - k) {
monoQueue.shift();
}
// 滑动窗口中的最大值就是队列首部的元素,简单明了
const maxInWindow = nums[monoQueue[0]];
// 将答案收入囊中,为下一次胜利做好准备
console.log(`滑动窗口中的最大值是:${maxInWindow}`);
}
拨开迷雾,直指核心
无论你选择扩展运算符和最大值子数组的组合,还是剑走偏锋的单调队列,这些方法的本质都是相同的——它们都在不断地寻找滑动窗口内的最大值。扩展运算符和最大值子数组的方法就像是用一把重剑,劈开前方的荆棘;而单调队列就像是一柄利刃,以迅捷的速度刺穿障碍。
这道题的意义,不在于哪种方法更好,而在于让我们认识到算法世界里的多种可能性。我们应该不断磨砺自己的解题能力,掌握不同的方法,以应对千变万化的挑战。
终点线上的思考
当你读完这篇文章,希望你已经对 LeetCode 239 题有了更深的理解。算法与编程的世界里,总会有新的挑战等待着我们,愿我们都能在不懈的探索中,不断进步,不断超越自我。