Java:在某个集合中查找最接近的数字

时间:2013-10-27 01:17:11

标签: java

我有一组静态的有序数字{1,2,4,10,14,20,21,24,29,30},可以存储在任何集合中。如果传入新号码,我需要能够找到最接近新号码的号码。

例如: 如果我的静态有序数集是{1,2,4,10,14,20,21,24,29,30}。 传入的数字是23,最接近的数字是24。

我考虑过将静态数字存储到数组中。循环数组,然后尝试找到最接近的数字,但此解决方案是O(n)。有更快的方法吗?

3 个答案:

答案 0 :(得分:3)

假设整数数组已排序,那么您可以使用Arrays.binarySearch(array, key)

binarySearch调用的结果是数组中键的偏移量或“插入点”;即需要插入密钥的偏移量。如果获得插入点(表示为负数),则可以使用它来标识数组中的下一个最大或下一个最小数字。 (“插入点”的确切含义和表示在javadoc中进行了解释。)

此程序的复杂性为O(logN)


这比使用Collections.binarySearch更快,因为后者需要将int[]转换为Integer[],然后才能将其包装在列表中。如果你开始使用Integer[],那么Arrays.binarySearch的替代重载将适用于任何对象数组。

它也比从输入数组创建TreeSet更快。但是,TreeSet的优势在于,一旦创建了集合,与基于数组或基于arraylist的表示相比,更新将更便宜。 (但更新不是上述要求的一部分。)

答案 1 :(得分:1)

在Java 1.6中,有NavigableSet接口。 TreeSet和ConcurrentSkipListSet都实现了这个接口。它是SortedSet的子接口,用于替换SortedSet。

所以,你现在已经在这个NavigableSet中获得了你的收藏。您现在有两个方法 - floorceiling分别返回小于或大于参数的元素,如果有一个则返回相等,如果没有这样的元素则返回null。

有了这个,你可以做一些事情:

int closest(int arg) {
    Integer ceil = set.ceiling(arg);
    Integer floor = set.floor(arg);

    if(ceil == null) { return floor; }
    if(floor == null) { return ceil; }

    int cdiff = ceil - arg;
    int fdiff = arg - floor;

    if(cdiff < fdiff) { return ceil; }
    else { return floor; }
}

意识到对于小型阵列,此实现与其他实现之间的速度差异可能可以忽略不计。

如果您正在处理大量数字,您可能希望实现自己的skip list(它是一个整齐的数据结构),其底层是双重链接。然后你可以到达值应该的地方,如果不是,可以轻松上下水平以获得下一个更高和更低的数字。

答案 2 :(得分:0)

如果您有有序列表,可以将其放在列表中并拨打Collections.binarySearch(list, valueToCheck)

如果返回索引为负,那么您需要将其转换为相应的正索引并确保该数字大于传入的数字(应将其转换为正数,只需注意它是否为正数)大于列表中的最后一个数字。)