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

双指针专题(二):两头堵的智慧——「有序数组的平方」

哈喽各位,我是前端小L。

场景想象:

给你一个已经排好序的数组 [-4, -1, 0, 3, 10]。

我们要把每个数平方,然后组成一个新的有序数组。

  • 直觉做法:先把每个数平方[16, 1, 0, 9, 100],然后调用sort()排序。

  • 问题sort()的复杂度是 $O(N \log N)$。面试官通常会问:“能不能用 $O(N)$ 解决?”

思考:

数组其实已经“部分”有序了。

  • 负数部分:越往左,绝对值越大,平方后越大。

  • 正数部分:越往右,绝对值越大,平方后越大。

    也就是说,最大的平方数,一定是在数组的最左边或者最右边! 不可能在中间。

力扣 977. 有序数组的平方

https://leetcode.cn/problems/squares-of-a-sorted-array/

题目分析:

  • 输入:按非递减顺序排序的数组nums(包含负数)。

  • 输出:每个数字的平方组成的新数组,也要按非递减顺序排序。

例子:[-4, -1, 0, 3, 10]

  • 左边-4平方是16

  • 右边10平方是100

  • 100 > 16,所以100肯定是新数组里的老大(最后一名)。

核心思维:左右夹逼 + 逆序填充

既然最大的数一定在两头,那我们就派出两个指针:

  1. 左指针 (left):指向开头(处理负数)。

  2. 右指针 (right):指向结尾(处理正数)。

  3. 结果指针 (k):指向新数组的最后一个位置(因为我们要先找最大的,填到最后去)。

操作逻辑:

  1. 比较nums[left]的平方和nums[right]的平方。

  2. 谁大选谁

    • 如果左边大:把左边的平方填入结果数组的k位置,left移。

    • 如果右边大:把右边的平方填入结果数组的k位置,right移。

  3. k指针向前移动一格,准备填倒数第二大的数。

  4. left > right时,结束。

代码实现 (JavaScript)

JavaScript

/** * @param {number[]} nums * @return {number[]} */ var sortedSquares = function(nums) { let n = nums.length; // 创建一个等长的新数组,用来存放结果 let result = new Array(n); let left = 0; let right = n - 1; // k 指向结果数组的最后一个位置(倒着填) let k = n - 1; // 注意:这里是 left <= right // 因为最后当 left === right 时,剩下的那个元素也要处理(平方后填入) while (left <= right) { let leftSquare = nums[left] * nums[left]; let rightSquare = nums[right] * nums[right]; if (leftSquare > rightSquare) { // 左边的平方更大,填入末尾 result[k] = leftSquare; left++; // 左指针向内收缩 } else { // 右边的平方更大(或相等),填入末尾 result[k] = rightSquare; right--; // 右指针向内收缩 } // 填完一个,k 往前挪一位 k--; } return result; };

深度模拟

输入:[-4, -1, 0, 3, 10]

  1. 初始L=0(-4),R=4(10),k=4

    • 比较:(-4)²=16vs10²=100

    • 选右边。res[4] = 100R变成 3。k变成 3。

    • 状态:[-4, -1, 0, 3],res=[?, ?, ?, ?, 100]

  2. 第二轮L=0(-4),R=3(3)。

    • 比较:16vs9

    • 选左边。res[3] = 16L变成 1。k变成 2。

    • 状态:[-1, 0, 3],res=[?, ?, ?, 16, 100]

  3. 第三轮L=1(-1),R=3(3)。

    • 比较:1vs9

    • 选右边。res[2] = 9R变成 2。k变成 1。

  4. ...以此类推,直到填满。

总结

这道题展示了双指针处理有序数组的强大能力。

  • 只要看到“有序数组”或者“数组部分有序”,且要求找“最大/最小/目标和”,第一反应就应该是左右指针

  • 关键技巧:“从两头往中间找,从后往前填结果”


下一题预告:三数之和

接下来我们要进入双指针专题的深水区了—— LC 15. 三数之和 (Medium)。

这是大厂面试中出现频率最高的算法题之一(绝对的 Top 5)。

  • 题目:给你一个数组,判断是否存在三个数a, b, c使得a + b + c = 0?找出所有不重复的三元组。

  • 难点:

    1. 怎么把三数之和降维?(还是用双指针)。

    2. 怎么去重?(比如数组里有三个-1,怎么保证不输出重复的结果?这是最容易写出 Bug 的地方)。

准备好迎接这道必考题了吗?

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

相关文章:

  • 持续性能测试:DevOps流水线中的关键一环
  • 2025年终AI智能床垫品牌推荐:基于权威榜单与用户口碑的TOP5排名揭晓。 - 十大品牌推荐
  • 双指针专题(三):去重的艺术——「三数之和」
  • vue基于springboot的指数基金数据分析系统
  • 2025年终中老年人智能床垫品牌推荐:聚焦健康监测功能的5强榜单深度解析。 - 十大品牌推荐
  • vue基于springboot的智能旅游推荐系统
  • 2025年聚焦:哪些盐水注射机公司赢得了市场好口碑?盐水注射机口碑排行综合实力与口碑权威评选 - 品牌推荐师
  • DroidCam局域网传输优化:提升手机到PC的稳定性实战案例
  • 如何为长辈挑选智能床垫?2025年终最新品牌综合评测及5款推荐! - 十大品牌推荐
  • 2025年终中老年人智能床垫品牌推荐:聚焦健康监测功能的5强品牌深度解析 - 十大品牌推荐
  • RK3588平台下aarch64与设备树交互机制深度解析
  • 2025年汽配采购必看:周边双主轴排刀机工厂推荐,刀塔机/46排刀机/Y轴/动力刀塔/双主轴/刀塔车床/三轴机排刀机定制推荐排行 - 品牌推荐师
  • lut调色包下载站点整合?视觉生成模型色彩校准新方向
  • paqsp.dll文件损坏丢失找不到 打不开程序 下载方法
  • vue基于springboot的信息技术论坛
  • 中老年人智能床垫哪个品牌更可靠?2025年终5大品牌横向评测与最终推荐! - 十大品牌推荐
  • GPTQ训练支持:逐层量化与误差补偿机制解析
  • 序列分类模型训练指南:情感分析与意图识别任务实战
  • 深度测评10个AI论文网站,MBA论文写作必备!
  • Megatron并行加速CPT/SFT/DPO全流程:200+模型已验证
  • GRPO训练方法详解:多模态场景下的强化学习优化策略
  • 如何为家中长者选择智能床垫?2025年终五大品牌横向评测及最终推荐! - 十大品牌推荐
  • C语言数据读写性能提升10倍的秘密(存算一体设计精髓)
  • 【专家级调优经验】:基于OpenMP 5.3的多核任务分配性能翻倍秘技
  • C语言如何精准调用汇编代码?昇腾算子库开发者必须掌握的3个关键点
  • 继续训练量化模型:BNB/AWQ/GPTQ是否可微调?
  • vue基于springboot的学生成绩管理系统
  • OpenAI接口兼容性测试:无缝迁移现有应用的可行性分析
  • vue基于springboot的学生考勤请假管理系统
  • 预训练数据准备规范:构建高质量语料库的技术要点