查找数组中最接近的数字
首先,我们必须在数组中查找是否存在所需的数字? 如果没有,那么我如何在Java中找到给定所需数字的更接近的数字?
一个主意:
int nearest = -1; int bestDistanceFoundYet = Integer.MAX_INTEGER; // We iterate on the array... for (int i = 0; i < array.length; i++) { // if we found the desired number, we return it. if (array[i] == desiredNumber) { return array[i]; } else { // else, we consider the difference between the desired number and the current number in the array. int d = Math.abs(desiredNumber - array[i]); if (d < bestDistanceFoundYet) { // For the moment, this value is the nearest to the desired number... bestDistanceFoundYet = d; // Assign new best distance... nearest = array[i]; } } } return nearest;
“更接近”的另一个常见定义是基于差异的平方。 大纲类似于romaintaz提供的大纲,除了你要计算
long d = ((long)desiredNumber - array[i]);
然后将(d * d)
与最近的距离进行比较。
请注意 ,我输入的d
为long
而不是int
以避免溢出,即使使用基于绝对值的计算也会发生溢出。 (例如,考虑当desiredValue
至少是最大32位有符号值的一半时会发生什么,并且数组包含具有相应幅度但负号的值。)
最后,我编写了返回值的索引的方法,而不是值本身。 在这两种情况中的任何一种:
- 当数组的长度为零时,和
- 如果你添加一个“tolerance”参数来限制你将考虑作为匹配的最大差异,
你可以使用-1
作为类似于indexOf
规范的带外值。
//这会有效
public int nearest(int of, List in) { int min = Integer.MAX_VALUE; int closest = of; for (int v : in) { final int diff = Math.abs(v - of); if (diff < min) { min = diff; closest = v; } } return closest; }
如果数组已排序,则执行修改后的二进制搜索。 基本上如果你没有找到数字,那么在搜索结束时返回下限。
伪代码返回最接近整数的列表。
myList = new ArrayList(); if(array.length==0) return myList; myList.add(array[0]); int closestDifference = abs(array[0]-numberToFind); for (int i = 1; i < array.length; i++) { int currentDifference= abs(array[i]-numberToFind); if (currentDifference < closestDifference) { myList.clear(); myList.add(array[i]); closestDifference = currentDifference; } else { if(currentDifference==closestDifference) { if( myList.get(0) !=array[i]) && (myList.size() < 2) { myList.add(array[i]); } } } } return myList;
Array.indexOf()
找出Array.indexOf()
元素是否存在。 如果不是,则迭代一个数组并维护一个变量,该变量保存所需元素和第i
个元素之间的差值的绝对值。 返回绝对差异最小的元素。
总体复杂度为O(2n) ,可以进一步减少到arrays上的单次迭代(即O(n) )。 虽然不会有太大的不同。
唯一缺少的是更接近的语义。
如果你正在寻找六个,你的arrays有四个和八个,你会怎么做?
哪一个最接近?
int d = Math.abs(desiredNumber - array[i]); if (d < bestDistanceFoundYet) { // For the moment, this value is the nearest to the desired number... nearest = array[i]; }
通过这种方式,您可以找到最接近所需数字的最后一个数字,因为bestDistanceFoundYet是常量,并且d记住最后一个值,使if (d <...) 。
如果你想通过所需的数字找到更近的数字WITH ANY DISTANCE( d是无关紧要的),你可以记住最后一个可能的值。 如果你可以测试
if(d
有几点需要指出:
1 – 您可以使用将数组转换为列表
Arrays.asList(yourIntegerArray);
2 – 使用列表,您可以使用indexOf()。
3 – 考虑一个场景,你有一个长度的列表,你想要最接近3的数字,你已经发现2在数组中,你知道3不是。 如果不检查其他数字,你可以得出结论,2是最好的,因为它不可能更接近。 我不确定indexOf()是如何工作的,所以这可能实际上并没有加快你的速度。
4 – 扩展为3,假设indexOf()不会花费更多时间来获取索引处的值。 然后,如果你想要一个数组中最接近3的数字并且你已经找到了1,并且还有更多的数字需要检查,那么检查数组中的2或4是否更快。
5 – 在3和4上扩展,我认为可以将它应用于浮点数和双精度数,尽管它需要使用小于1的步长…计算小的范围似乎超出了问题的范围,尽管。
// paulmurray's answer to your question is really the best : // The least square solution is way more elegant, // here is a test code where numbertoLookFor // is zero, if you want to try ... import java.util.* ; public class main { public static void main(String[] args) { int[] somenumbers = {-2,3,6,1,5,5,-1} ; ArrayList l = new ArrayList (10) ; for(int i=0 ; i() { public int compare(Integer n1, Integer n2) { return n1*n1 - n2*n2 ; } } ) ; Integer first = l.get(0) ; System.out.println("nearest number is " + first) ; } }
int[] somenumbers = getAnArrayOfSomenumbers(); int numbertoLookFor = getTheNumberToLookFor(); boolean arrayContainsNumber = new HashSet(Arrays.asList(somenumbers)) .contains(numbertoLookfor);
它也很快。
哦 – 你想找到最近的号码? 在这种情况下:
int[] somenumbers = getAnArrayOfSomenumbers(); int numbertoLookFor = getTheNumberToLookFor(); ArrayList l = new ArrayList ( Arrays.asList(somenumbers) ); Collections.sort(l); while(l.size()>1) { if(numbertoolookfor <= l.get((l.size()/2)-1)) { l = l.subList(0, l.size()/2); } else { l = l.subList(l.size()/2, l.size); } } System.out.println("nearest number is" + l.get(0));
哦 - 坚持:你是在追求最小二乘解决方案?
Collections.sort(l, new Comparator(){ public int compare(Integer o1, Integer o2) { return (o1-numbertoLookFor)*(o1-numbertoLookFor) - (o2-numbertoLookFor)*(o2-numbertoLookFor); }}); System.out.println("nearest number is" + l.get(0));