阅读Finding three elements in an array whose sum is closest to a given number后,这是我尝试实现此类算法
def findThree(seq, goal):
# initialize the differences
goalDifference = float("inf")
dl = -1
dr = -1
dx = -1
for x in range(len(seq)-1):
left = x+1
right = len(seq)-1
while (left < right):
# if the absolute value of the previous set and the goal is less than the current goalDifference,
# keep track of the new set
if(abs(goal - (seq[left] + seq[right] + seq[x])) < goalDifference):
dl = left
dr = right
dx = x
tmp = seq[left] + seq[right] + seq[x]
if tmp > goal:
right -= 1
elif tmp < goal:
left += 1
else:
return [seq[left],seq[right],seq[x]]
# if no match is found, return the closest set
return [seq[dl],seq[dr], seq[dx]]
该算法非常适合找到精确的解决方案,给定
arr = [89, 120, 140, 179, 199, 259, 259, 259, 320, 320]
findThree(arr, 349) // want to get [120, 140, 89]
>> [120, 140 89] // success
findThree(arr, 439) // want to get [140, 179, 120]
>> [140, 179,120] // success
然而,当我想看它是否会返回最近的时候,它会返回
findThree(arr, 350) // only 1 more than 349, should return [120, 140, 89]
>> [320, 320, 259] // fail
findThree(arr, 440) // only 1 more than 439, should return [140, 179, 120]
>> [320, 320, 259] // fail
似乎当我希望它返回“cloest”元素时,它总是返回[320,320,259]。我一直在看代码几个小时,但仍然无法弄清楚是什么问题。
答案 0 :(得分:4)
我很快查看了你的代码,主要的问题是“目标差异”从未改变过。
你需要随意挤出“净胜球”,否则所有组合都在“球门差异”范围内,显然你最终会将最后一组作为答案。
答案 1 :(得分:0)
您可以执行以下操作:
def find3(tgt, arr):
lowest=[float('inf')]
for i in range(0,len(arr)-2):
j=i+1
k=len(arr)-1
while k>=j:
t=tuple(arr[x] for x in (i, j, k) )
sum_t=sum(t)
if sum_t==tgt:
return t
elif sum_t<sum(lowest):
lowest=t
if sum_t>0:
k-=1
else:
j+=1
return lowest
适用于您描述的所有案例。
答案 2 :(得分:0)
实际上,这里的问题是你没有跟踪最接近的数字组合。根据当前算法,您的代码会检查组合,直到left = right-1
和x=left-1 (since left = x+1);
。在循环执行结束时,如果未实现正确的组合,您将始终拥有x=259
,left=320
和right=320
。这就是为什么当调用[320, 320, 259]
和findThree(arr, 350)
时,它返回最后一次迭代的值总是findThree(arr, 440)
。
一个解决方案可能是采用三个变量close1
close2
和close3
并在for循环开始之前将它们初始化为0
;并且在for循环之后在if语句之后添加以下内容:
if(abs(goal - (seq[left] + seq[right] + seq[x])) < abs(goal - (close1 + close2 + close3)) ):
close1 = seq[left]
close2 = seq[right]
close3 = seq[x]
上述语句将检查最接近上一组和当前数组的left
,right
和x
元素,并更改close1
,{{1如果当前组合比close2
,close2
和left
的上一条记录更接近,则{}}和right
到当前的左,右和x集合,x
和close1
存储在{{}分别为1}},close2
和close3
。否则close1
,close2
和close3
不得更改。
并在代码的末尾
#if no match is found,return the closest set
return [close1 ,close2, close3]