从已经排序的数组中查找数字X的地板和ceil。 e.g。
a [] = {3,7,9,10,15}
- 如果X = 2,floor = N / A,ceil = 3
- 如果X = 3,floor = 3,ceil = 3
- 如果X = 4,floor = 3,ceil = 7
- 如果X = 16,floor = 15,ceil = N / A
我认为我们大多数人都知道解决方案,即我们可以通过修改二进制搜索找到floor / ceil。但是修改二进制搜索的问题是我们需要处理很多边界条件。但我发现相同的二元搜索算法确实有效,但对于地板我们只需要写if low > high return low
和ceil if low > high return high
。如果floor返回-1则显示N / A,如果ceil返回的值大于数组索引而不是显示N / A.
algo for floor:
int floorSearch(int a[], int low, int high, int x)
{
if(low > high){
return low;
}
int mid = (low+high)/2;
if(a[mid]>x){
return floorSearch(a, low, mid-1, x);
}
else if(a[mid]<x){
return floorSearch(a, mid+1, high, x);
}
else{
return mid;
}
}
和ceil:
int ceilSearch(int a[], int low, int high, int x)
{
if(low > high){
return high;
}
int mid = (low+high)/2;
if(a[mid]>x){
return ceilSearch(a, low, mid-1, x);
}
else if(a[mid]<x){
return ceilSearch(a, mid+1, high, x);
}
else{
return mid;
}
}
这很简单,不是吗?我检查了很多输入,它确实有效,但我未能证明算法的正确性。有人可以尝试证明正确性,或者您也可以提供此算法失败的样本输入。感谢。
答案 0 :(得分:1)
关于如何进行证明的提示:
这些算法的正确性证明将遵循算法的递归结构;即使用结构感应证明(查阅)。
查看标准二进制搜索的证明并弄清楚它是如何构建的。
如果您的代码中存在错误,那么您应该无法找到正确的证明;见其他评论和其他答案!
答案 1 :(得分:1)
代码中存在传统错误。它使用int mid = (low+high)/2;
。如果数组非常大,则可能会使加法溢出为负结果,使得中间为负数。
可以使用int mid = (low+high)>>>1;
修复错误,就像在java.util.Arrays binarySearch方法中所做的那样。 >>> 1
实际上是无符号除以2。
答案 2 :(得分:0)
由于您只修改了条件if(low > high)
,请注意在普通二进制搜索中等效的内容。理解二进制搜索的证明,在这里确定正确性应该是微不足道的。
答案 3 :(得分:0)
这是一个测试案例,它会破坏你的ceilSearch代码。
a = {3,7,9,11,13},x = 10.
我在每个递归调用中列出低,高和中:
(0,4,2) - &gt; a [2] = 9&lt; X
(3,4,3) - &gt; a [3] = 11&gt; X
(3,2,2) - &gt;低&gt;高,返回低= 2。
正确答案是3,而不是2。