假设我有一个包含n
个整数的数组
如何找到大小为k
的子集,使得子集中所有整数对之间的minimum
距离为maximized
,我的意思是它们距离最远。
示例:数组a[]={1,2,6,7,10}
和k=3
,
subset = {1,6,10}
,最小距离为4
,介于10到6之间
错误的子集:
{1,7,10}
,最小距离为3
{1,2,6}
,最小距离为1
我想出了一个解决方案:
1)排序阵列
2)选择一个[0],现在在数组中找到ceil(a [0] + x
)= Y ....然后是ceil(Y + x
),依此类推k-1
时间,第k个元素也将是a[n-1]
查找x
:
dp[i,j]
是x
,用于从第一个i元素中选择j个元素
最后,我们希望dp[n][k]
<{1}}
但我在寻找x
时遇到了问题。
dp [i,j] = max(min(dp [k,j-1],dp [i] -A [k]))
在k = 1到i-1,i = 2到n,j = 2到idp [i] [1] = 0,i = 1到n
编辑:我想纠正动态编程解决方案,虽然我知道x可以通过二进制搜索x找到。
更新2 :我已更新代码,但仍无法获得正确的解决方案。请指出错误 代码:http://ideone.com/J5vvR9
更新3 :感谢@Gassa,@ Niklas B.和@Fallen提供的答案!
答案 0 :(得分:2)
如果时间允许搜索以获取x
的可能值,我认为查找 x
没有必要。只需添加外部循环,这将是对答案的二元搜索(即最小距离,我们称之为x
)。
修复x
后,您可以从a[0]
开始贪婪地选择值。下一个选定的值将是a[i]
最小i
和a[i] - a[0] >= x
。第三个是a[j]
,j
最小,a[j] - a[i] >= x
,依此类推。如果您能够以这种方式选择至少k
个值,则实际答案至少是当前x
;如果没有,答案就小于x
。
总运行时间为O(n log(C)),其中C是数组中可能值的总数。比如说,如果数组中的整数是0到1000000,C将是1000001,log(C)(向上舍入)将是20.首先,你尝试x = 500000
;如果它失败了,你留下的范围是[0; 500000)答案;如果没有,范围[500000; 1000000]等。
答案 1 :(得分:2)
基数应该是:
dp[i][1] = INFINITY for i = 1 to n
原因是minimum of an empty set是正无穷大。
实际上,对于某些a[i] - a[j]
和i
,任何大于j
的最大值的整数都可以作为INFINITY
常量。
此外,正确的过渡将是:
dp[i,j] = max{for k=1 to i-1} (min(dp[k,j-1], a[i]-a[k]))
答案 2 :(得分:1)
对X值进行二进制搜索。然后对于每个这样的x,编写一个DP / Greedy函数,检查是否存在一个结果(元素之间的最大距离)大于或等于X的数组。 / p>
正确性如果对于任何X,我们可以有M个元素,使得它们之间的最小距离大于或等于X,然后对于每个x,x&lt; X,至少这个相同的数组将作为结果服务器。并且对于任何X,如果没有M个元素,使得元素之间的最小距离大于或等于X,则对于无x,x> 0。 X,M这样的元素是可用的。所以我们可以在X上进行二进制搜索。