查找边界之间数组中所有整数的最快方法

时间:2018-06-19 21:36:24

标签: java arrays algorithm

最快的方法是获取数组中两个边界之间的所有值。两个界限都是包容的。在数组中,可以有重复项,在这种情况下,它应该返回所有值。

例如,如果我有一个数组:[1 1 3 3 4 6 7 7 8 10]和边界[2, 7],则程序将返回[3 3 4 6 7 7]

我知道我可以做一个循环并遍历每个元素以检查它是否在范围之内,但是我想知道是否有更快的方法。数组已排序,因此我考虑过进行二进制搜索,但不确定如何运行。

谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用Arrays.binarySearch(int[], key)查找上下边界元素,无论它们是否存在。给定边界lowhighsubRange()方法应能满足您的需求:

/* returns the index first/last occurrence of a value, or one past 
   where the element would have been if missing */
static int indexOf(int array[], int bound, boolean last) {
  int index = Arrays.binarySearch(array, bound);
  if (last && index >= 0) {
    while (index < array.length && array[index] == bound) index++;
  }
  return index < 0 ? -index - 1 : index;
}

static int subRange(int a[], int low, int high) {
  return Arrays.copyOfRange(a, indexOf(a, low, false), indexOf(a, high, true));
}

主要的尴尬是处理上限(last == true情况),因为binarySearch返回 first 元素的索引,因此您需要浏览以查找最后一个元素。我很确定某个地方存在一个错误的错误,对于那些不理解而复制它的读者来说,这是一个惊喜。

使用第二个搜索(使用在数组的子范围上运行的Arrays.binarySearch的版本),可以将第二个搜索限制在第一个搜索找到的索引右边的范围内,这是可能的。如果您想真正获得 铁杆,则可以编写自己的自定义二进制搜索,该搜索一次包含两个元素,然后一次搜索两个元素:在搜索开始时,只要当前中点低于或高于两者,您实际上实际上是免费地缩小了两个元素的范围(与单个值搜索相比)。 mid拆分低键和高键后,您将以当前范围为起点进行单独的二进制搜索。当lowhigh非常接近时,此功能特别有用:有效地将搜索时间缩短了一半。

答案 1 :(得分:0)

由于数组已排序,因此您正在数组的中间寻找一个切片。 因此,您需要找到数组中最低界限的位置,然后找到上限的相同位置(从末尾开始)。这些位置之间的数组元素就是结果数组。

您基本上在开始和结束时都删除了不需要的数字:

    int[] arr = new int[]{1, 1, 3, 3, 4, 6, 7, 7, 8, 10};
    int low=2;
    int up=7;
    int lowIdx=0;
    int upIdx=arr.length-1;
    for(int i=0;i<arr.length;i++){
        lowIdx = i;
        if(arr[i] >= low){
            break;
        }
    }
    for(int i = arr.length-1;i>=0;i--){
        if(arr[i] <= up){
            break;
        }
        upIdx = i;
    }
    System.out.println(Arrays.toString(Arrays.copyOfRange(arr, lowIdx, upIdx)));

prints [3, 3, 4, 6, 7, 7]

这容易吗?并不是的。这是稍微复杂的代码,它利用了数组已排序的事实。

答案 2 :(得分:0)

最简单的方法是:

int[] arr = {1, 1, 3, 3, 4, 6, 7, 7, 8, 10};
int min = 2;
int max = 7;
int[] result = IntStream.of(arr).filter(x -> x >= min && x <= max).toArray();

另一种这样做的方法是使用循环,该循环只需要迭代一半以上的循环,在很多情况下,由于需要遍历整个数组以找到最后一个索引,因此它比binarysearch快。元素,具有两个查找。循环周期:

        int minIndex = arr.length;
        int maxIndex = 0;
        for(int i = 0; i < arr.length / 2; i++)
        {
            if(arr[i] >= min && i < minIndex)
                minIndex = i;
            int j = arr.length-i-1;
            if(arr[j] <= max && j > maxIndex)
                maxIndex = j;
        }
        int[] res = Arrays.copyOfRange(arr,minIndex,maxIndex+1);