鉴于long
随机数和目标长的无序数组很大,找到最接近数字的最有效算法是什么?
@Test
public void findNearest() throws Exception {
final long[] numbers = {90L, 10L, 30L, 50L, 70L};
Assert.assertEquals("nearest", 10L, findNearest(numbers, 12L));
}
答案 0 :(得分:8)
迭代一次longs数组。存储当前最接近的数字和该数字的距离。如果距离较近,请继续检查每个号码,并在遇到更接近的号码时更换当前最接近的号码。
这可以让你获得最佳的O(n)表现。
按照其他回答者的建议构建二叉树将需要O(nlogn)。当然,未来的搜索只需要O(logn)...所以如果你做了很多搜索,它可能是值得的。
如果您是专业人士,可以将其与openmp或线程库并行化,但我猜这不属于您的问题范围。
答案 1 :(得分:1)
如果您不打算在阵列上执行多个此类请求,则没有比每个数字的强力线性时间检查更好的方法。
如果你要在同一个阵列上做多个请求,先对它进行排序,然后对它进行二进制搜索 - 这样可以减少这些请求到O(log(n))的时间,但你还是要支付O(n *) log(n))用于排序,所以这只有在请求数量相当大的情况下才合理,即k * n>>(然后大很多)n * log(n)+ k * log(n)其中k是请求的数量。
如果数组将更改,则创建一个binary search tree并对其执行下限请求。如果最接近的数字请求与数组更改请求相比较大,并且还与元素数量相比,这也是合理的。由于构建树的成本是O(n * log(n)),并且更新它的成本是O(logn),你需要有k * log(n)+ n * log(n)+ k * log (n)<(然后小很多)k * n
答案 2 :(得分:1)
恕我直言,我认为您应该使用二进制堆(http://en.wikipedia.org/wiki/Binary_heap),其插入时间为O(log n),为O (n log n)表示整个数组。对我来说,关于二进制堆的最酷的事情是它可以在你自己的数组内部进行,没有开销。看看 heapfy部分。
“Heapfying”您的数组可以在O(1)中获得更大/更低的元素。
答案 3 :(得分:0)
如果您从数字构建二进制搜索树并搜索。在最坏的情况下,O(log n)将是复杂的。在你的情况下,你不会搜索相等,你将通过减法寻找最小的返回值
答案 4 :(得分:0)
我会在迭代数组时检查数字之间的差异,并为该差异保存最小值。
如果你打算多次使用findNearest,我会在排序时使用排序算法(使用复杂度为n * log(n)的排序算法)来计算差异
答案 5 :(得分:0)
完成这项工作的时间复杂是O(n),数字的长度。
final long[] numbers = {90L, 10L, 30L, 50L, 70L};
long tofind = 12L;
long delta = Long.MAX_VALUE;
int index = -1;
int i = 0;
while(i < numbers.length){
Long tmp = Math.abs(tofind - numbers[i]);
if(tmp < delta){
delta = tmp;
index = i;
}
i++;
}
System.out.println(numbers[index]); //if index is not -1
但如果你想多次找到不同的值,比如12L对同一个数字数组,你可以先对数组进行排序,然后对有序数字数组进行二进制搜索。
答案 6 :(得分:0)
如果您的搜索是一次性的,您可以像使用输入值作为枢轴一样对快速排序中的数组进行分区。
如果你跟踪 - 在分区时 - 右半部分中的最小项目和左半部分中的最大项目,你应该在O(n)和单个数组中通过它。
我会说它不可能在小于O(n)的情况下完成,因为它没有排序,你必须至少扫描输入。
如果您需要进行许多后续搜索,那么BST确实可以提供帮助。
答案 7 :(得分:0)
您可以在以下步骤中执行此操作
第1步:对数组进行排序
第2步:查找搜索元素的索引
第3步:根据索引显示右边和右边的数字。左侧
如有任何疑问,请告诉我......