-
Notifications
You must be signed in to change notification settings - Fork 633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
腾讯&leetcode15:三数之和 #31
Comments
//这道题经典的是细节,需要考虑蛮多细节的
//解法:
//1.暴力破解,三层枚举,O(n^3)效率太低不考虑
//2.a+b+c = 0,转换思路,a+b = -c,这不就是两数之和嘛?
//3.利用双指针夹逼,但是怎么避免重复呢?
//3.1 排序即可,利用排序好的数组,固定一个指针i,夹逼选举left和right
//3.2 这道题难度在于要考虑的细节太多,多想想即可。
//3.3 扩展一下,如果是4数之和,五数之和,N数之和呢?怎么解决?
const threeSum = (nums) => {
const len = nums.length
const result = []
// 因为是三数之和,小于三个不用考虑了
if(len < 3){
return result
}
nums.sort((a, b) => a - b)
// len - 2 同样道理,小于三个不用考虑
for(let i = 0; i < len - 2; i++){
// 如果第一个就大于0了,三个加起来肯定大于0
if(nums[i] > 0){
break
}
// 避免掉重复的情况
if(i && nums[i] === nums[i - 1]){
continue
}
let left = i + 1
let right = len - 1
// 双指针夹逼
while(left < right){
const sum = nums[i] + nums[left] + nums[right]
if(sum === 0){
result.push([nums[i], nums[left++], nums[right--]])
// push 加了之后防止还存在重复
while(nums[left] === nums[left - 1]){
left++
}
while(nums[right] === nums[right + 1]){
right--
}
}else if(sum > 0){
right--
}else{
left++
}
}
}
return result
} |
@huangruitian // 双指针夹逼
while(left < right){
const sum = nums[i] + nums[left] + nums[right]
if(sum === 0){
result.push([nums[i], nums[left++], nums[right--]])
// push 加了之后防止还存在重复
while(nums[left] === nums[left - 1]){
left++
}
while(nums[right] === nums[right + 1]){
right--
}
}else if(sum > 0){
// 这里可以使用二分法进一步加快寻找符合条件的 right, 即 nums[right]= 0 - nums[i] - nums[left]
// right--
}else{ // 同理也可以用二分法加快逼近速度
// left++
}
}
} |
不错,对left 和 right的寻找速度用二分法确实是一个优化,很棒!K数之和的复杂度也补充得很棒。 |
解法: 排序 + 双指针我们可以继续按照两数之和的思路解题,遍历数组,选定一个数( 但会出现一个问题:结果中可能会出现重复的三元组 const threeSum = function(nums) {
let map = new Map()
let result = []
for(let i = 0; i < nums.length - 2; i++) {
// 第一个数
let first = nums[i]
for(let j = i+1; j < nums.length; j++) {
// 第三个数
let second = 0 - nums[j] - first
if(map.has(second)) {
result.push([first, second, nums[j]])
}
map.set(nums[j], j)
}
map.clear()
}
return result
};
// 测试
var nums = [-1, 0, 1, 2, -1, -4]
threeSum(nums)
// [[-1,0,1],[-1,2,-1],[0,1,-1]]
// 存在重复元组 你可以尝试着去除重复元组,但花费的时间、空间复杂度就高了 感谢 @thxiami 的补充,我们可以使用排序去重: const threeSum = function (nums) {
let set = new Set() // 使用 Set() 即可满足需求, 相对节省内存
let result = []
nums.sort((a, b) => (a - b))
for(let i =0; i < nums.length - 2; i++) {
while (nums[i] === nums[i - 1]) {i++} // 去重
// 第一个数
let first = nums[i]
let j = i + 1
while (j < nums.length) {
// 第三个数
let second = 0 - nums[j] - first
let third = nums[j]
if(set.has(second)) {
result.push([first, second, third])
set.add(third)
j++
while (nums[j] === nums[j-1]) {j++} // 去重
} else {
set.add(third)
j++
}
}
set = new Set()
}
return result
}; 这里介绍另一种思路解法:排序 + 双指针 为了防止结果数组中加入重复的元素,我们可以将 解题思路: 先数组排序,排序完后遍历数组,以
直至 代码实现: const threeSum = function(nums) {
if(!nums || nums.length < 3) return []
let result = [], second, last
// 排序
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
second = i + 1
last = nums.length - 1
while(second < last){
const sum = nums[i] + nums[second] + nums[last]
if(!sum){
// sum 为 0
result.push([nums[i], nums[second], nums[last]])
// 去重
while (second<last && nums[second] === nums[second+1]) second++
while (second<last && nums[last] === nums[last-1]) last--
second ++
last --
}
else if (sum < 0) second ++
else if (sum > 0) last --
}
}
return result
}; |
@sisterAn var threeSum = function (nums) {
let set = new Set() // 使用 Set() 即可满足需求, 相对节省内存
let result = []
nums.sort((a, b) => (a - b))
for(let i =0; i < nums.length - 2; i++) {
while (nums[i] === nums[i - 1]) {i++} // 去重
// 第一个数
let first = nums[i]
let j = i + 1
while (j < nums.length) {
// 第三个数
let second = 0 - nums[j] - first
let third = nums[j]
if(set.has(second)) {
result.push([first, second, third])
set.add(third)
j++
while (nums[j] === nums[j-1]) {j++} // 去重
} else {
set.add(third)
j++
}
}
set = new Set()
}
return result
}; |
const nums = [-1, 0, 1, 2, -1, -4]
const threeSum = (nums) => {
const res = []
nums = nums.sort((a, b) => a - b)
for (let i = 0; i < nums.length - 2; i++) {
const first = nums[i]
if (first > 0) break
if (i && nums[i] === nums[i - 1]) {
continue
}
let l = i + 1
let r = nums.length - 1
while (l < r) {
const sum = first + nums[l] + nums[r]
if (sum === 0) {
res.push([first, nums[l], nums[r]])
l++
r--
while (l < r && nums[l] === nums[l - 1]) l++
while (l < r && nums[r] === nums[r + 1]) r--
}
if (sum < 0) {
let high = r
let mid
while (l <= high) {
mid = Math.floor((l + high) / 2)
if (first + nums[mid] < -nums[r]) {
l = mid + 1
} else if (first + nums[mid] > -nums[r]) {
hight = mid - 1
} else {
l = mid
break
}
}
l++
}
if (sum > 0) {
let low = l
let mid
while (low <= r) {
mid = Math.floor((low + r) / 2)
if (first + nums[mid] < -nums[l]) {
low = mid + 1
} else if (first + nums[mid] > -nums[l]) {
r = mid - 1
} else {
r = mid
break
}
}
r--
}
}
}
return res
} |
你这个实现有问题 |
|
|
给你一个包含
n
个整数的数组nums
,判断nums
中是否存在三个元素a
,b
,c
,使得a + b + c = 0
?请你找出所有满足条件且不重复的三元组。注意: 答案中不可以包含重复的三元组。
示例:
附赠leetcode地址:leetcode
可结合 字节&leetcode1:两数之和 一起查看
The text was updated successfully, but these errors were encountered: