Java 找到最窄区间的算法,其中m将覆盖一组数字
假设您有一个n数字列表。您可以选择m整数(让我们调用整数a)。对于每个整数a,删除包含范围[a-x,a+x]内的每个数字,其中x是一个数字。可以清除列表的x的最小值是多少 例如,如果您的数字列表是 138108205 m=2,答案是x=5 您可以选择两个整数5和20。这将清除列表,因为它会删除[5-5,5+5]和[20-5,20+5]之间的所有数字 我该如何解决这个问题?我认为解决方案可能与动态规划有关。我不想要暴力方法解决方案Java 找到最窄区间的算法,其中m将覆盖一组数字,java,c++,algorithm,dynamic-programming,knapsack-problem,Java,C++,Algorithm,Dynamic Programming,Knapsack Problem,假设您有一个n数字列表。您可以选择m整数(让我们调用整数a)。对于每个整数a,删除包含范围[a-x,a+x]内的每个数字,其中x是一个数字。可以清除列表的x的最小值是多少 例如,如果您的数字列表是 138108205 m=2,答案是x=5 您可以选择两个整数5和20。这将清除列表,因为它会删除[5-5,5+5]和[20-5,20+5]之间的所有数字 我该如何解决这个问题?我认为解决方案可能与动态规划有关。我不想要暴力方法解决方案 代码将非常有用,最好是在java或C++或C. < P>一个有效的
代码将非常有用,最好是在java或C++或C.</P> < P>一个有效的算法可以(假设列表排序)->/P>
我希望这个算法的工作原理非常清楚 我认为这也是类似的集群化问题。例如,您可以使用k-means聚类算法:在m个类上对初始列表进行分区,对于x,将最大大小除以两个获得的类。 假设你有名单
1 3 8 10 18 20 25
想知道如果x等于2,需要多少组来覆盖这个集合
您可以通过贪婪的方式解决这个问题,方法是选择第一个整数为1+x(1是列表中最小的数字)。这将覆盖1+x+x=5的所有元素。然后简单地重复这个过程,直到所有的数字都被覆盖
在这种情况下,下一个未覆盖的数字是8,所以我们选择8+x=10,覆盖第二组中10+x=12的所有数字
同样,第三组将涵盖[18,24],第四组将涵盖[25,29]
这个x值需要4组。这太多了,所以我们需要增加x并重试
您可以使用二分法来确定x的最小值,该值覆盖m组中的所有数字 递归解决方案:
首先,你需要一个估计值,你可以分成m组,然后估计值(x)必须是~(greather-lowerelement)/2*m。估计的(x)可能是一个解决方案。如果有更好的解决方案,它在所有组中的x值都低于extimated(x)!你可以检查第一组,然后递归地重复。问题一直在减少,直到你只有一组:最后一组,你知道你的新解决方案是否更好,如果有更好的,你可以用它来放弃另一个更糟糕的解决方案
private static int estimate(int[] n, int m, int begin, int end) {
return (((n[end - 1] - n[begin]) / m) + 1 )/2;
}
private static int calculate(int[] n, int m, int begin, int end, int estimatedX){
if (m == 1){
return estimate(n, 1, begin, end);
} else {
int bestX = estimatedX;
for (int i = begin + 1; i <= end + 1 - m; i++) {
// It split the problem:
int firstGroupX = estimate(n, 1, begin, i);
if (firstGroupX < bestX){
bestX = Math.min(bestX, Math.max(firstGroupX, calculate(n, m-1, i, end, bestX)));
} else {
i = end;
}
}
return bestX;
}
}
public static void main(String[] args) {
int[] n = {1, 3, 8, 10, 18, 20, 25};
int m = 2;
Arrays.sort(n);
System.out.println(calculate(n, m, 0, n.length, estimate(n, m, 0, n.length)));
}
私有静态int估计(int[]n,int m,int begin,int end){
返回(((n[end-1]-n[begin])/m)+1)/2;
}
私有静态int计算(int[]n,int m,int开始,int结束,int估计dx){
如果(m==1){
返回估计(n,1,开始,结束);
}否则{
int bestX=估计值dx;
对于(int i=开始+1;i估计){
long estimatedIsland=估算值(n,1,islandBegin,i+1);
加上(新长[{estimatedIsland,islandBegin,i,1});
islandBegin=i+1;
}
}
long estimatedIsland=估算值(n,1,islandBegin,end);
添加(新长[{estimatedIsland,islandBegin,end,1});
长期结果;
if(islands.isEmpty()| | m0){
long[]island=islands.poll();
岛[3]++;
孤岛[0]=解算器(n,孤岛[3],(int)孤岛[1],(int)孤岛[2]);
岛屿。添加(岛屿);
姆弗里--;
}
结果=islands.poll()[0];
}
返回结果;
}
公共静态void main(字符串[]args){
长[]n=新长[63];
对于(int i=1;i
1)您应该研究算法的时间和空间复杂性方面的最佳情况、平均情况和最坏情况复杂性
2) 我认为大卫·佩雷斯·卡布雷拉的想法是正确的。让我们假设平均情况(如下面的伪代码)
3) 让整数列表用l表示
keepGoing = true
min_x = ceiling(l[size-1]-l[0])/(2m)
while(keepGoing)
{
l2 = l.copy
min_x = min_x-1
mcounter = 1
while(mcounter <= m)
{
firstElement = l2[0]
// This while condition will likely result in an ArrayOutOfBoundsException
// It's easy to fix this.
while(l2[0] <= firstElement+2*min_x)
{ remove(l2[0]) }
mcounter = mcounter+1
}
if(l2.size>0)
keepGoing = false
}
return min_x+1
到目前为止你试过什么了吗?我对要求有点困惑。m个整数不需要来自列表(例如,示例中的整数5),当您选择它们时,您可以充当对手-试图找到最差的m个整数。因此,x的最小值必须足够大,以处理最坏的情况,无论选择哪个m整数。但既然m整数没有约束,为什么在示例中不选择-50000000000和+50000000000,显著增加所需的x值?或者“对手”有点错误?选择m个整数是否是解决问题的最佳选择?二进制搜索Vx,使用经典贪婪覆盖算法验证guess@BobBilly你能检查一下我的答案吗?我在想清单1、2、3、4、5、6、7。。。100设m=2。这个例子的算法是如何工作的?好的。现在有两组->[1,2,…50]和[51,52,…100],前半部分50-1=49,后半部分100-51=49,它们的最大值=49,所以x=49/2…但我认为我们应该将“ans”增加到“ans”+1,这样ans=25。。或使用“ceil”功能。。现在25-25,25+25,75-25,75+25。。整个列表很清楚。它适用于我给出的示例,但不适用于老师较长的示例(列表中有数千个数字)。它们太长,无法在此处复制/粘贴。你知道为什么有时候这样不行吗?我
keepGoing = true
min_x = ceiling(l[size-1]-l[0])/(2m)
while(keepGoing)
{
l2 = l.copy
min_x = min_x-1
mcounter = 1
while(mcounter <= m)
{
firstElement = l2[0]
// This while condition will likely result in an ArrayOutOfBoundsException
// It's easy to fix this.
while(l2[0] <= firstElement+2*min_x)
{ remove(l2[0]) }
mcounter = mcounter+1
}
if(l2.size>0)
keepGoing = false
}
return min_x+1
l = {1, 2, 3, 4, 5, 6, 7}, m=2 (gives x=2)
l = {1, 10, 100, 1000, 10000, 100000, 1000000}, m=2
l = {1, 10, 100, 1000, 10000, 100000, 1000000}, m=3