I am trying to solve a problem where,
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
My solution is: take a number out (number_1) from the array, set the target to target - that number and find two other numbers which are closest to the new target. This way: number_1 + number_2 + number_3 will be closest as number_2 + number_3 will be closest to target - number_1.
I tried my solution at https://leetcode.com/problems/3sum-closest/description/ .
My solution is:
def threeSumClosest(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
closest_sum = nums[0] + nums[1] + nums[2]
for i in range(len(nums)):
# Create temp array excluding a number
if i!=len(nums)-1:
temp = nums[:i] + nums[i+1:]
else:
temp = nums[:len(nums)-1]
# Sort the temp array and set new target to target - the excluded number
temp = sorted(temp)
l, r = 0, len(temp) -1
t = target - nums[i]
while(l<r):
if temp[l] + temp[r] == t:
return target
elif temp[l] + temp[r] > t:
if abs(temp[l] + temp[r] + nums[i] - target) < abs(closest_sum - target):
closest_sum = temp[l] + temp[r] + nums[i]
r = r - 1
else:
if abs(temp[l] + temp[r] + nums[i] - target) < abs(closest_sum - target):
closest_sum = temp[l] + temp[r] + nums[i]
l = l + 1
return closest_sum
It passes 80 test cases out of 125, so the solution logic looks fine enough for me.
It fails for:
Input:
[0,2,1,-3]
1
Output:
3
Expected:
0
Can't understand why it fails and how to make my logic consistent.
Thanks for your help.
You have couple of mistakes the first one is silly, you have an extra indentation in return closest
and the second one is not checking updating closest
in the 3rd if statement. This code got accepted:
class Solution(object):
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
closest = nums[0] + nums[1] + nums[2]
#if len(nums)==3:
# return closest
for i in range(len(nums)):
if i!=len(nums)-1:
temp = nums[:i] + nums[i+1:]
else:
temp = nums[:len(nums)-1]
temp = sorted(temp)
l, r = 0, len(temp) -1
t = target - nums[i]
while(l < r):
if abs(temp[l] + temp[r] + nums[i] - target) < abs(closest - target):
closest = temp[l] + temp[r] + nums[i]
if temp[l] + temp[r] == t:
return target
elif temp[l] + temp[r] > t:
r = r - 1
else:
l = l + 1
return closest
And this is an accepted C++ solution with O(n^2)
running time:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int ans = nums[0] + nums[1] + nums[2];
for(int i = 0; i < nums.size() - 2; i++) {
int l = i + 1, r = nums.size() - 1;
while (l < r) {
if(abs(nums[i] + nums[l] + nums[r] - target) < abs(target - ans)) {
ans = nums[i] + nums[l] + nums[r];
}
if(nums[r] + nums[l] > target - nums[i]) r = r - 1;
else l = l + 1;
}
}
return ans;
}
};
As we worked out in the comments the last return
statment was erroneously inside the for
loop cutting it short after the first iteration. Also, closest
should be updated in both branches where we overshoot or undershoot the target.
I think an obvious improvement of your algorithm would be to sort first. Removing individual elements doesn't destroy order, so you'd need to sort only once. That would get you from O(n^2 log n) to O(n^2).
You can find all combinations of values in the list, and then find the listing whose sum is closest to the target:
import itertools
s = [{'vals':[-1, 2, 1, -4], 'target':1}, {'vals':[0,2,1,-3],'target':1}]
final_result = {tuple(a['vals']):sum(min(itertools.combinations(a['vals'], 3), key=lambda x:abs(a['target']-sum(x)))) for a in s}
Output:
{(-1, 2, 1, -4): 2, (0, 2, 1, -3): 0}
My solution works for this input:
[0,2,1,-3] 1
Your closest sum variable is incorrect. See my variable named "gap"
class Solution:
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
sorted_nums = sorted(nums)
gap = sorted_nums[len(nums)-1] * 10000
solution = 0
for pointer_1 in range(len(sorted_nums)):
pointer_2 = pointer_1 + 1
pointer_3 = len(sorted_nums) - 1
while(pointer_2 < pointer_3):
gap_n = abs((sorted_nums[pointer_1]+sorted_nums[pointer_2]+sorted_nums[pointer_3]) - target)
add = (sorted_nums[pointer_1]+sorted_nums[pointer_2]+sorted_nums[pointer_3])
if (gap_n < gap):
solution = add
gap = gap_n
elif (target > add):
pointer_2 = pointer_2 + 1
else:
pointer_3 = pointer_3 - 1
return solution
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.