LeetCode 之 JavaScript 解答第十五题 —— 三数之和(3Sum)

Time:2019/4/3

Title:3Sum

Difficulty: medium

Author:小鹿

题目三:ADD Two Numbers

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:
The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

Solve:

▉ 算法思绪:

1、直接用三个 for 轮回遍历一切数据,找出相符前提的数据,时候复杂度为 O(n^3)。能不能更快效力?

2、先对数组内数据举行一次排序。O(nlogn)

3、最外层一个 for 轮回,先把个中一个值固定住(寄存到变量),然后分别用两个指针指向数据的非固定值的头部和尾部,经由过程 while 轮回来遍历。

4、假如三个数据相加即是 0 了,就存储该三个值且更新 head 和 end 指针。

5、假如不即是小于或大于 0 ,就更新 head 和 end 指针挪动从新查找相符前提的值。

6、返回效果集 result。

▉ 边界前提:

1、推断数组内元素是不是都为整数或负数,直接返回。

2、推断固定值、head 以及 end 指针的值前后元素是不是雷同,去掉反复盘算。

3、推断 head 和 end 指针的大小关联。

4、注重去掉反复数据

▉ 代码完成:
  /**
  * @param {number[]} nums
  * @return {number[][]}
  */

var threeSum = function(nums) {
    //用来存取末了效果集
    let result = new Array();
    //头指针
    let head;
    //尾指针
    let end;
    //固定值
    let fixedVal;

    //排序
    nums.sort((a, b) => {
        return a-b;
    });
    
    //推断数组内元素是不是都为整数或负数,直接返回
    if(nums[0] > 0 || nums[nums.length - 1] < 0) return result;
    
    // 最先遍历
    for (let i = 0; i < nums.length; i++) {
        //固定值
        fixedVal = nums[i];
        // 假如前后元素雷同,跳过此次轮回(固定值)
        if(fixedVal === nums[i-1]) continue;
        //一最先的固定值为nums[0],所以头指针为 i+1 下一个元素
        head = i+1;
        //尾指针
        end = nums.length - 1;
        //假如头指针小于尾指针元素
        while(head < end){
            //推断固定值+头指针+尾指针是不是即是0
            if(nums[head] + nums[end] + fixedVal === 0){
                //声明数组,寄存这三个值
                let group =  new Array();
                group.push(nums[head]);
                group.push(nums[end]);
                group.push(fixedVal);
                result.push(group);
                //寄存终了以后,不要遗忘头指针和尾指针的挪动(不然会发生死轮回)
                head += 1;
                end -= 1;
                //假如头指针满足小于尾指针且挪动后的指针和挪动前的指针元素相称,再往前挪动
                while(head < end && nums[head] === nums[head - 1]){
                    head += 1;
                }
                 //假如头指针满足小于尾指针且挪动后的指针和挪动前的指针元素相称,再往后挪动
                while(head < end && nums[end] === nums[end + 1]){
                    end -= 1;
                }
             //小于 0 须要挪动头指针,由于尝试着让数据比原有数据大一点
            }else if(nums[head] + nums[end] + fixedVal < 0){
                head++;
            }else{
                //不然,尾指针向前挪动,让数据小于元数据
                end--;
            }
        } 
    }
    return result;
}
//测试
let nums = [-1, 0, 1, 2, -1, -4];
threeSum(nums);
▉ sort 排序:

定义:sort() 要领用于对数组的元素举行排序。 在本来数组上举行排序,不天生副本。

运用:

1)无参:依据字母的递次对元素排序,即便是数字,先转换 String 再排序(依据字符编码),每每得不到我们要的效果。

2)有参:参数为比较函数,比较函数有两个参数 a,b (默许的 a 是小于 b 的)

  • 若 a 小于 b,在排序后的数组中 a 应当出现在 b 之前,则返回一个小于 0 的值。(从小到大)
  • 若 a 即是 b,则返回 0。(依据无参排序)
  • 若 a 大于 b,则返回一个大于 0 的值。(从大到小)

内部完成:

在 Chrome 浏览器中 sort 的你内部完成是疾速排序,然则 FireFox 内部运用的合并排序,二者的区分就是疾速排序不如合并排序稳固,然则大多数状况下照样能够运用快排的,只要一般请求必需稳固。所谓的稳固性就是原始数据雷同的元素在排序以后位置是不是转变?

机能题目:

1、sort 会发生机能题目,由于无论是快排照样合并,都涉及到递归,假如递归深度过大,致使客栈溢出,v8 引擎的解决办法就是设置一个递归深度阈值,小于阀值采纳插入排序,大于阀值改用快排。

2、快排在在最差的状况下算法也会退步,由于依据 pivot 挑选的差别,最坏状况时候复杂度退步到 O(n^2).

3、怎样举行革新?有兴致能够看下方参考链接!

参考链接:https://efe.baidu.com/blog/ta…

迎接一同加入到 LeetCode 开源 Github 堆栈,能够向 me 提交您其他言语的代码。在堆栈上对峙和小伙伴们一同打卡,配合完美我们的开源小堆栈!
Github:https://github.com/luxiangqia…

迎接关注我个人民众号:「一个不甘寻常的码农」,记录了本身一起自学编程的故事。

    原文作者:小鹿
    原文地址: https://segmentfault.com/a/1190000018768594
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞