最快的方法是获取数组中两个边界之间的所有值。两个界限都是包容的。在数组中,可以有重复项,在这种情况下,它应该返回所有值。
例如,如果我有一个数组:[1 1 3 3 4 6 7 7 8 10]
和边界[2, 7]
,则程序将返回[3 3 4 6 7 7]
。
我知道我可以做一个循环并遍历每个元素以检查它是否在范围之内,但是我想知道是否有更快的方法。数组已排序,因此我考虑过进行二进制搜索,但不确定如何运行。
谢谢!
答案 0 :(得分:1)
您可以使用Arrays.binarySearch(int[], key)
查找上下边界元素,无论它们是否存在。给定边界low
和high
,subRange()
方法应能满足您的需求:
/* 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
拆分低键和高键后,您将以当前范围为起点进行单独的二进制搜索。当low
和high
非常接近时,此功能特别有用:有效地将搜索时间缩短了一半。
答案 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)));
这容易吗?并不是的。这是稍微复杂的代码,它利用了数组已排序的事实。
答案 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);