Time:2019/4/3
Title:3Sum
Difficulty: medium
Author:小鹿
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. javascript
Note:
The solution set must not contain duplicate triplets.java
Example:git
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
Solve:github
一、直接用三个 for 循环遍历全部数据,找出符合条件的数据,时间复杂度为 O(n^3)。能不能更快效率?二、先对数组内数据进行一次排序。O(nlogn)算法
三、最外层一个 for 循环,先把其中一个值固定住(存放到变量),而后分别用两个指针指向数据的非固定值的头部和尾部,经过 while 循环来遍历。编程
四、若是三个数据相加等于 0 了,就存储该三个值且更新 head 和 end 指针。数组
五、若是不等于小于或大于 0 ,就更新 head 和 end 指针移动从新查找符合条件的值。浏览器
六、返回结果集 result。函数
一、判断数组内元素是否都为整数或负数,直接返回。二、判断固定值、head 以及 end 指针的值先后元素是否相同,去掉重复计算。性能
三、判断 head 和 end 指针的大小关系。
四、注意去掉重复数据
/** * @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() 方法用于对数组的元素进行排序。 在原来数组上进行排序,不生成副本。
使用:
1)无参:按照字母的顺序对元素排序,即使是数字,先转换 String 再排序(按照字符编码),每每得不到咱们要的结果。
2)有参:参数为比较函数,比较函数有两个参数 a,b (默认的 a 是小于 b 的)
- 若 a 小于 b,在排序后的数组中 a 应该出如今 b 以前,则返回一个小于 0 的值。(从小到大)
- 若 a 等于 b,则返回 0。(按照无参排序)
- 若 a 大于 b,则返回一个大于 0 的值。(从大到小)
内部实现:
在 Chrome 浏览器中 sort 的你内部实现是快速排序,可是 FireFox 内部使用的归并排序,二者的区别就是快速排序不如归并排序稳定,可是大多数状况下仍是可使用快排的,只有个别要求必须稳定。所谓的稳定性就是原始数据相同的元素在排序以后位置是否改变?
性能问题:
一、sort 会产生性能问题,由于不管是快排仍是归并,都涉及到递归,若是递归深度过大,致使堆栈溢出,v8 引擎的解决办法就是设置一个递归深度阈值,小于阀值采用插入排序,大于阀值改用快排。
二、快排在在最差的状况下算法也会退化,由于根据 pivot 选择的不一样,最坏状况时间复杂度退化到 O(n^2).
三、怎么进行改进?有兴趣能够看下方参考连接!
欢迎一块儿加入到 LeetCode 开源 Github 仓库,能够向 me 提交您其余语言的代码。在仓库上坚持和小伙伴们一块儿打卡,共同完善咱们的开源小仓库!
Github:https://github.com/luxiangqia...