Algorithm 二进制搜索边界
我总是在这方面遇到最困难的时候,我还没有看到一个明确的解释,这个解释被认为是如此普遍和高度使用 我们已经知道标准的二进制搜索。给定起始下限和上限,在(下限+上限)/2处找到中点,然后将其与数组进行比较,然后相应地重新设置边界,以此类推 但是,调整搜索以查找所需的差异是什么(对于升序列表):Algorithm 二进制搜索边界,algorithm,binary-search,Algorithm,Binary Search,我总是在这方面遇到最困难的时候,我还没有看到一个明确的解释,这个解释被认为是如此普遍和高度使用 我们已经知道标准的二进制搜索。给定起始下限和上限,在(下限+上限)/2处找到中点,然后将其与数组进行比较,然后相应地重新设置边界,以此类推 但是,调整搜索以查找所需的差异是什么(对于升序列表): 最小值>=目标 最小值>目标 最大值二进制搜索(至少是我实现它的方式)依赖于一个简单的属性——谓词在区间的一端为true,在另一端不为true。我总是认为我的时间间隔在一端关闭,另一端打开。让我们来看一下这个
int beg = 0; // pred(beg) should hold true
int end = n;// length of an array or a value that is guranteed to be out of the interval that we are interested in
while (end - beg > 1) {
int mid = (end + beg) / 2;
if (pred(a[mid])) {
beg = mid;
} else {
end = mid;
}
}
// answer is at a[beg]
这将适用于您定义的任何比较。只需将pred
替换为=target
或target
循环结束后,a[beg]
将是给定不等式适用的最后一个元素
因此,让我们假设(如评论中所建议的)我们想要找到最大的数字,
a[i]基本的二进制搜索是搜索与目标键相等的位置/值。而它可以扩展到找到满足某些条件的最小位置/值,或找到满足某些条件的最大位置/值
假设数组是升序的,如果没有找到满意的位置/值,则返回-1
代码示例:
// find the minimal position which satisfy some condition
private static int getMinPosition(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) >> 1;
// feel free to replace the condition
// here it means find the minimal position that the element not smaller than target
if(arr[m] >= target) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
// find the maximal position which satisfy some condition
private static int getMaxPosition(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) >> 1;
// feel free to replace the condition
// here it means find the maximal position that the element less than target
if(arr[m] < target) {
ans = m;
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
}
int[] a = {3, 5, 5, 7, 10, 15};
System.out.println(BinarySearchTool.getMinPosition(a, 5));
System.out.println(BinarySearchTool.getMinPosition(a, 6));
System.out.println(BinarySearchTool.getMaxPosition(a, 8));
//找到满足某些条件的最小位置
私有静态int getMinPosition(int[]arr,int目标){
int l=0,r=arr.length-1;
int ans=-1;
而(l>1;
//请随意更换该条件
//这里它意味着找到元素不小于目标的最小位置
如果(arr[m]>=目标){
ans=m;
r=m-1;
}否则{
l=m+1;
}
}
返回ans;
}
//找到满足一定条件的最大位置
私有静态int getMaxPosition(int[]arr,int目标){
int l=0,r=arr.length-1;
int ans=-1;
而(l>1;
//请随意更换该条件
//这里的意思是找到元素小于目标的最大位置
如果(arr[m]<目标){
ans=m;
l=m+1;
}否则{
r=m-1;
}
}
返回ans;
}
int[]a={3,5,5,7,10,15};
System.out.println(BinarySearchTool.getMinPosition(a,5));
System.out.println(BinarySearchTool.getMinPosition(a,6));
System.out.println(BinarySearchTool.getMaxPosition(a,8));
您需要的是一个二进制搜索,它允许您参与最后一步的过程。典型的二进制搜索将接收(数组、元素)
,并生成一个值(通常是索引或未找到)。但是,如果您有一个修改过的二进制文件,它接受在搜索结束时调用的函数,则可以覆盖所有情况
例如,在Javascript中,为了便于测试,下面的二进制搜索
function binarySearch(array, el, fn) {
function aux(left, right) {
if (left > right) {
return fn(array, null, left, right);
}
var middle = Math.floor((left + right) / 2);
var value = array[middle];
if (value > el) {
return aux(left, middle - 1);
} if (value < el) {
return aux(middle + 1, right);
} else {
return fn(array, middle, left, right);
}
}
return aux(0, array.length - 1);
}
函数二进制搜索(数组、el、fn){
辅助功能(左、右){
如果(左>右){
返回fn(数组,空,左,右);
}
var middle=数学楼层((左+右)/2);
var值=数组[中间];
如果(值>el){
返回辅助(左,中-1);
}如果(值
将允许您使用特定的返回函数覆盖每个案例
- 默认值
函数(a,m){return m;}
- 最小值>=目标
函数(a,m,l,r){返回m!=null?a[m]:r+1>=a.length?null:a[r+1];}
- 最小值>目标
函数(a,m,l,r){return(m | | r)+1>=a.length?null:a[(m | | r)+1]}
- 最大值0?a[l-1]:null;}
函数(a,m,l,r){return(m | | l)-1<0?null:a[(m | | l)-1]}
在我发现循环不变量和谓词是处理所有二进制问题的最佳和最一致的方法之前,我遇到了完全相同的问题 第1点:想想谓词
一般来说,对于所有这4种情况(以及对等式的正常二进制搜索),假设它们是谓词。因此,这意味着一些值满足谓词,有些则失败。因此,请考虑这个数组,其目标为5: [1,2,3,4,6,7,8]。查找大于5的第一个数字基本上等同于查找此数组中的第一个数字:[0,0,0,0,1,1] 第2点:搜索边界(包括在内)
我喜欢两端总是包含。但我可以看到一些人喜欢开始包含和结束独占(在len而不是len-1上)。我喜欢数组中的所有元素,所以当提到[mid]时,我不认为这是否会给我一个超出范围的数组。所以我的偏好是:包含
第三点:当循环条件出现时,我不理解这个问题;“最小值”和“最大值”分别是数组最左边和最右边位置的值吗?这是一个家庭作业问题吗?问其他问题似乎很奇怪。@StilesCrisis一点也不明白。这只是我一次又一次遇到的问题@Codor是的,对不起。假设数组是按升序排序的。你是在问如果目标不在数组中它是如何工作的吗…?你能用一个例子p详细说明一下吗
// find the minimal position which satisfy some condition
private static int getMinPosition(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) >> 1;
// feel free to replace the condition
// here it means find the minimal position that the element not smaller than target
if(arr[m] >= target) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
// find the maximal position which satisfy some condition
private static int getMaxPosition(int[] arr, int target) {
int l = 0, r = arr.length - 1;
int ans = -1;
while(l <= r) {
int m = (l + r) >> 1;
// feel free to replace the condition
// here it means find the maximal position that the element less than target
if(arr[m] < target) {
ans = m;
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
}
int[] a = {3, 5, 5, 7, 10, 15};
System.out.println(BinarySearchTool.getMinPosition(a, 5));
System.out.println(BinarySearchTool.getMinPosition(a, 6));
System.out.println(BinarySearchTool.getMaxPosition(a, 8));
function binarySearch(array, el, fn) {
function aux(left, right) {
if (left > right) {
return fn(array, null, left, right);
}
var middle = Math.floor((left + right) / 2);
var value = array[middle];
if (value > el) {
return aux(left, middle - 1);
} if (value < el) {
return aux(middle + 1, right);
} else {
return fn(array, middle, left, right);
}
}
return aux(0, array.length - 1);
}
public int find(int a[], int target){
int start = 0;
int end = a.length - 1;
while (start <= end){
int mid = (start + end) / 2; // or for no overflow start + (end - start) / 2
if (a[mid] < target)
start = mid + 1;
else // a[mid] >= target
end = mid - 1;
}
return start; // or end + 1;
}
return end; // or return start - 1;