三数求和算法

题目

给你一个包含 n 个整数的数组 nums ,判断 nums 中是否存在三个元素 abc ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。( 注意:答案中不可以包含重复的三元组。)

假设:

  • nums[-1, 0, 1, 2, -1, -4]
  • 应返回 [ [-1, 0, 1], [-1, -1, 2] ]

算法优化解析

  1. 所有 求和 的问题都可以转换为 求差
  2. 像这题目普遍做法是三层循环嵌套,但这时间复杂度就是 O(n^3) ,应该考虑用空间换时间,尽可能的少遍历。

像这倒题目:

  • 采取固定最左边的第一个(i),剩下的两个使用 双指针 的方法,一左(j = i+ 1)一右(k = nums.length - 1)
  • 如果 nums[i] + num[j] + nums[k] > 0 ,说明右边指针太大,应向左移(k--),若左移后的值是重复值再向左移。
  • 如果 nums[i] + num[j] + nums[k] < 0 ,说明左边指针大小,应向右移(j++),若右移后的值是重复值再向右移。
  • 如果 nums[i] + num[j] + nums[k] === 0 ,就是这三个,加到结果数组中。

完整代码

const threeSum = (nums) => {
  // 先从小到大排序 nums
  const data = nums.sort((a, b) => a - b)
  // 结果数组
  const res = []
  // 缓存 nums 的长度
  const len = nums.length
  
  // 注意,遍历到倒数第三个就可以了,因为左右指针会遍历后面两个数
  for (let i = 0; i < nums.length - 2; i++) {
    // 左指针
    let j = i + 1
    // 右指针
    let k = len - 1

    // 如果遇到重复的数字,则跳过
    if (i > 0 && nums[i] === nums[i-1]) {
      continue
     }

    while (j < k) {
      // 如果加起来大于 0 ,右指针往左移
      if (data[i] + data[j] + data[k] > 0) {
        k--
        // 如果往左移后值还是相等,继续移动
        while (data[k] === data[k + 1]) {
          k--
        }
      } else if (data[i] + data[j] + data[k] < 0) {
        // 如果加起来小于 0 ,左指针往右移
        j++
        // 如果往右移后值还是相等,继续移动
        while (data[j] === data[j - 1]) {
          j++
        }
      } else {
        // 如果加起来等于 0,得到目标数字组合,推入结果数组
        res.push([data[i], data[j], data[k]])        
        // 左右指针都往中间移动
        j++
        k--

        // 有重复都跳过
        while (data[j] === data[j - 1]) {
          j++
        }
        while (data[k] === data[k + 1]) {
          k--
        }
      }
    }
  }
 return res
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 1 链表反转 2 链表两两反转 3 判断链表是否有环 3.1 头结点开始遍历,直到位NULL(卡时间,避免死循环...
    289d3a591637阅读 352评论 0 0
  • 题目链接:三数之和 1.题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a...
    站在海边看远方阅读 290评论 0 0
  • 目录 1 左神部分集锦 2 Leetcode前150题 3 牛客网剑指offer 4 JavaG 5 题目中的...
    小小千千阅读 991评论 0 0
  • 整理了校招面试算法题,部分《剑指offer》算法题,以及LeetCode算法题,本博文中算法题均使用Java实现校...
    heyrenly阅读 780评论 0 4
  • 简述 极客时间算法40讲中所出现的leetcode算法题 题目 【链表】reverse-linked-list(反...
    BestbpF阅读 4,473评论 0 4