三数之和-leetcode1-5

题目

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

输入:nums = []
输出:[]

提示

  • 0 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

咋一看,首先想到来个暴力穷举,三个数的话我们需要三层循环 ==> O(n * n *n )。 这个就不用试了,

肯定过不了的。看看怎么能把这个优化吧, 优化方向 O( n * n * n) ==> O (nn) ==> O(nlogn)。 在前面盛水最多的容器那题,我们使用了双指针技巧 成功把 O(n*n) 降到了 O(n) . 是不是很爽? 那当然,这里我们也可以继续用,毕竟是存储结构是数组。划重点存储结构为数组的,我们可以尝试用双指针法. 同时,排序后的数组使用二分查找的速度更快!

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    let result = [];
  
	  // 对数组排序
    nums = nums.sort((a,b)=>a-b);
  	// 这里遍历很有技巧,假设第一个数最大,第二个数第二大,第三个数最小
    for (let i = 0; i < nums.length;i++){
        if (nums[i] > 0) break;
      	// 排除值相同的元素
        if (i > 0 && nums[i] === nums[i-1]) continue;
      
      	// 熟悉的双指针
        let left = i+1;
        let right = nums.length - 1;
      	// 双指针开始工作
        while (left < right){
            const sum = nums[i] + nums[left] + nums[right];
          	// 根据临时的sum来移动
            if (sum > 0) {
                right --;
            } else if(sum < 0 ) {
                left ++;
            } else {
              	// 找到结果后的操作,第一入栈,第二排除相同元素,为下一次做准备
                result.push([nums[i],nums[left],nums[right]]);
                while (left < right && nums[left ] === nums[left+1]){
                    left ++;
                }
                while (left < right && nums[right] === nums[right - 1]){
                    right --;
                }
                left ++;
                right --;
            }
        }
    }
    return result;
};

总结

​ 数组题目无非以下几种方法:

  1. 穷举
  2. 双指针
  3. 二分(排序后的数组)
  4. 哈希
posted @ 2021-04-04 23:32  HelloCoderRookie  阅读(48)  评论(0编辑  收藏  举报