题目一
最接近的三数之和
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
思路1:
最简单的就是暴力求解,直接遍历数组,三重循环,时间复杂度达到O(n) = n^3,具体代码如下(网上copy):
func threeSumClosest(nums []int, target int) int {
n:=len(nums)
path:=math.MaxInt64
//res 就是最后返回的三数之和,初始化为几都可以,最后结果和这个初始化的值无关。res初始化下面的值都可以!!!
//res :=0
//res :=10
res :=nums[0]+nums[1]+nums[2]
for i:=0;i<n;i++{
for j:=i+1;j<n;j++{
for k:=j+1;k<n;k++ {
//距离不断地缩小,然后对res进行刷新
if x :=nums[i]+nums[j]+nums[k];abs(target-x)<path{
res =x
//path:用来进行标记,求出来的三数之和到target的距离
path=abs(target-x)
}
}
}
}
return res
}
思路2:
外层循环:指针i遍历数组
内层循环:用双指针,寻找sum与target差值绝对值得最小元素
先排序的意义:
使用双指针进行缩减遍历范围
func threeSumClosest(nums []int, target int) int {
result := nums[0] + nums[1] + nums[2]
sort.Ints(nums)
for i := 0; i < len(nums)-2; i++ {
start := i + 1
end := len(nums) - 1
for {
if start < end {
sum := nums[i] + nums[start] + nums[end]
if abs(sum-target) < abs(result-target) {
result = sum
}
if sum < target {
start++
} else if sum > target {
end--
} else {
return sum
}
} else {
break
}
}
}
return result
}
func abs(num int) int {
if num < 0 {
return -num
} else {
return num
}
}
题目二
三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
分析
本题总体思路与上题相似,难点是不能包含重复的三元组,这就需要进行双指针的遍历,避免出现重复解
- 左指针在保证在start<end 的情况下,如果碰到相同的值就让start++实现右移
- 右指针在保证在start<end 的情况下,如果碰到相同的值就让end–实现左移
查看题解发现可以对算法进行优化
在算法中首先对排序后的数组第一个元素进行判断, 如果大于0,则直接break
func threeSum(nums []int) [][]int {
ans := [][]int{}
sort.Ints(nums)
for i := 0; i < len(nums)-2; i++ {
if i >= 1 && nums[i] == nums[i-1] {
continue
}
start := i + 1
end := len(nums) - 1
target := nums[i]
for start < end {
sum := nums[start] + nums[end]
res := []int{nums[i], nums[start], nums[end]}
if sum+target == 0 {
ans = append(ans, res)
for start < end && nums[start] == nums[start+1] {
start++
}
for start < end && nums[start] == nums[end-1] {
end--
}
start++
end--
} else if sum+target > 0 {
end--
} else if sum+target < 0 {
start++
}
}
}
return ans
}