算法_三/四数之和

一、三数之和

题目:

给你⼀个包含 n 个整数的数组 nums ,判断 nums 中是否存在三个元素 a b c ,使得 a + b + c = 0 ?
请你找出所有满⾜条件且不重复的三元组。
注意:一个三元组中元素不能重复,对应的索引不同,值是可以相同的

示例:

 

给定数组 nums =[1, 0, -1, 0, 0] ,和 target = 0
满⾜要求的三元组集合为:
[
        [-1, 0, 1 ] ,
        [0, 0, 0 ]
]

要点:

  • 双指针搭配排序数组
  • 固定第一个数,然后再设置两个指针,左指针 p 指向固定的数的后⾯那个值, 右指针 q 指向最后⼀个值,两个指针相向⽽⾏。
  • 根据 arr[ p ] + arr[ q ] 和 target - arr[ i ]的大小关系,移动pq指针
  • 注意重复元素的跳过问题——指针每次更新都需要检查
      // 三数之和
      function threeSum(arr, target) {
        arr.sort((a, b) => a - b);
        const res = [];
        const len = arr.length;
        for (let i = 0; i < len - 2; i++) {
          // 如果有重复数字就跳过
          if (i > 0 && arr[i] === arr[i - 1]) {
            continue;
          }

          const remain = target - arr[i];
          // 初始化双指针
          let p = i + 1;
          let q = len - 1;
          while (p < q) {
            const sum = arr[p] + arr[q];
            if (sum === remain) {
              res.push([arr[i], arr[p++], arr[q--]]);
              // 重复元素跳过
              while (p < q && arr[p] === arr[p - 1]) {
                p++;
              }
              while (p < q && arr[q] === arr[q + 1]) {
                q--;
              }
            } else if (sum < remain) {
              p++;
              // 重复元素跳过
              while (p < q && arr[p] === arr[p - 1]) {
                p++;
              }
            } else {
              q--;
              // 重复元素跳过
              while (p < q && arr[q] === arr[q + 1]) {
                q--;
              }
            }
          }
        }
        return res;
      }

二、四数之和

题目基本同三数之和,只是换成四个数之和了

要点: 

  • 固定两个数字,然后再初始化两个指针,两个指针的移动同三数之和类似
  • 做完题之后,考虑一些快速结束的情况,提高性能
      // 四数之和
      function fourSum(arr, target) {
        const res = [];
        arr.sort((a, b) => a - b);
        const len = arr.length;
        for (let i = 0; i < len - 3; i++) {
          // 如果有重复数字就跳过
          if (i > 0 && arr[i] === arr[i - 1]) {
            continue;
          }
          // 三数之和
          for (let j = i + 1; j < len - 2; j++) {
            // 如果有重复数字就跳过
            if (j > i + 1 && arr[j] === arr[j - 1]) {
              continue;
            }
            // 快速跳出,提高性能
            if (arr[i] + arr[i + 1] + arr[i + 2] + arr[i + 3] > target) {
              break;
            }
            const remain = target - arr[i] - arr[j];
            // 初始化双指针
            let p = j + 1;
            let q = len - 1;
            while (p < q) {
              const sum = arr[p] + arr[q];
              if (sum === remain) {
                res.push([arr[i], arr[j], arr[p++], arr[q--]]);
                // 重复元素跳过
                while (p < q && arr[p] === arr[p - 1]) {
                  p++;
                }
                while (p < q && arr[q] === arr[q + 1]) {
                  q--;
                }
              } else if (sum < remain) {
                p++;
                // 重复元素跳过
                while (p < q && arr[p] === arr[p - 1]) {
                  p++;
                }
              } else {
                q--;
                // 重复元素跳过
                while (p < q && arr[q] === arr[q + 1]) {
                  q--;
                }
              }
            }
          }
        }
        return res;
      }

 

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值