给定数字 current
,找到数组中大于和小于该值的值的数量 .
//sort array for binary search
int[] digits = Arrays.stream(sc.nextLine()
.split(" "))
.mapToInt(Integer::parseInt)
.sorted()
.toArray();
//for duplicate values, find higher index of current.
while(low <= high){
int mid = low + (high - low)/2;
if(digits[mid] > current){
high = mid - 1;
}else if (digits[mid] == current){
startindex = mid;
high = mid - 1;
}else{
startindex = mid;
low = mid +1;
}
}
//for duplicate values, find lower index of current.
int endindex = -1;
low = 0;
high = no_digits - 1;
while(low <= high){
int mid = low + (high - low)/2;
if(digits[mid] > current){
high = mid - 1;
}else if (digits[mid] == current){
endindex = mid;
low = mid + 1;
}else{
endindex = mid;
low = mid + 1;
}
}
System.out.println(endindex + "-" + startindex);
if(digits[0] > current){
smallest = 0;
largest = no_digits;
System.out.println(String.format("Smaller: %d, Greater: %d", smallest, largest));
} else if (digits[no_digits - 1] < current){
smallest = no_digits;
largest = 0;
System.out.println(String.format("Smaller: %d, Greater: %d", smallest, largest));
}else {
smallest = startindex;
largest = no_digits - endindex - 1;
System.out.println(String.format("Smaller: %d, Greater: %d", smallest, largest));
}
}
}
样本输入:
5 8 7 2 4 3 7 9 1 9 - Array of ints.
7
0
100
3
6
输出:
Smaller: 5, Greater: 3
Smaller: 0, Greater: 10
Smaller: 10, Greater: 0
Smaller: 2, Greater: 7
Smaller: 5, Greater: 5
我的结果:
6-5 //start and end index.
Smaller: 5, Greater: 3
-1--1
Smaller: 0, Greater: 10
9-9
Smaller: 10, Greater: 0
2-2
Smaller: 2, Greater: 7
4-4
Smaller: 5, Greater: 4
我设法提出上述算法,该算法考虑的值大于或低于数组中的任何值 .
但是,由于我需要在O((N Q)log N)时间内完成上述操作,因此我无法找到解释数组中不存在的值而不迭代数组的解决方案 .
在这种情况下,这将是最后一个测试用例,其值为 6
. 数组中不存在6,但我仍然需要计算高于/低于6的所有值 .
6 回答
二进制搜索算法为数组中不存在的值生成"insertion point" . 你的
startIndex
和endIndex
会给你第一个"eligible"项目,或者它旁边的项目 . 换句话说,如果您要查找小于6
的所有值,搜索 endpoints 将产生5
的索引 .请注意,您不需要使用自己的二进制搜索算法:Java为您提供了一个实现 .
参考:Arrays.binarySearch
EDIT 问题已被编辑,现在它包含一个额外的要求,即算法应该能够快速地进行多个查询,更准确地说:整个运行时应该是
O((N + Q) * log(N))
,其中N
是数组的大小,Q
是查询的数量 .以下方法仅适用于
Q = 1
.我认为没有任何理由不在线性
O(N)
时间内这样做 .输出:
如果你坚持用流来做:
即使它遍历数组两次,它仍然是
O(N)
.因为你无论如何使用
Stream
,并且map
-call也不少,你无论如何都在迭代整个数组 .所以就这么做
或更通用的版本
见Arrays,这将在这里派上用场 .
如你所见,当找到一个元素时,回路O(N)就足够了,它小于排序O(N log N) .
更快 - O(log N)而不是O(N)用于该部分 - 如果可以对搜索的二进制搜索 - 0.5并且寻求0.5 .
这使用了加倍的整数,其缺点是数组值的有效域减半 .
在您的情况下,您自己的二进制搜索算法应该选择后一种情况(不加倍),使用隐式
sought + 0.5
,永远不会找到,寻找插入位置 .好的,所以在编辑之后你声明你想在同一个数组上运行几个查询,所以准备时间不那么重要了 .
为此,从数组中构建red-black tree;这将为您提供一个允许在O(log N)中搜索的排序结构 .
那么你对“较小”计数所做的就是向左移动,直到找到一个值等于或大于下限的节点;算上所有左边的孩子 . 模拟较大的(向右,找到相等或更小,向右计数) .
如果该项目不在数组中,则无关紧要,因为您正在寻找“等于或大于”的项目,如果6不存在,但是你找到了5,你会从那里算起来 - 只有你在计数中加1 .
You just have to filter and then count occurences. 例如: