所以,我必须在O(logn)中计算排序数组中数字的最低值,其中floor表示数组中小于给定数字的最大数字。
For example, let the input array be {1, 2, 8, 10, 10, 12, 19}
For x = 0: floor doesn't exist in array
For x = 1: floor = 1
For x = 5: floor = 2
For x = 20: floor = 19
我做了以下功能:
int bina (int arr[], int low, int high, int num)
{
if ( arr[low] > num )
return -1;
else if (arr[high] <= num )
return high;
int mid = (low+high)/2;
if ( arr[mid] == num )
return mid;
// floor of num lies from low to (mid-1)
else if (arr[mid] > num)
{
if ( (mid-1) >= low && arr[mid-1] < num )
return mid-1;
else
bina(arr, low, mid-1, num);
}
// floor of num lies between (mid+1) to high
else if ( arr[mid] < num )
{
if ( (mid+1) <= high && arr[mid+1] > num )
return mid;
else
bina(arr, low, mid+1, num);
}
}
主要通过呼叫bina(arr,0,k-1,n)
调用此方法。但是,在设置这些值时(在上面的示例中),它总是返回1.我不知道问题是什么。我交叉检查了我的逻辑3次,似乎是正确的。有人可以帮我吗?谢谢!
答案 0 :(得分:3)
最终案例中的代码看起来很可疑。
尝试更改:
bina(arr, low, mid+1, num);
到
return bina(arr, mid+1, high, num);
您可能还需要在行bina(arr, low, mid-1, num);
中添加一个返回值。
答案 1 :(得分:0)
通过稍微不同地查看作业,可以简化此任务的代码。就目前而言,循环的每次迭代基本上都有一个5向条件。
然而,当你开始讨论它时,如果我们保持在循环中,实际上只有两种可能的行动方式:我们继续搜索输入的左半部分,或者我们继续搜索右半部分。同样,退出循环时只需要一个条件:左侧和右侧缩小到一个点。
因为我已经用这种方式编写了代码,所以这里有一些通用形式的代码:
template <class Iter>
Iter lower_bound(Iter left,
Iter right,
typename std::iterator_traits<Iter>::value_type val)
{
while (left < right) {
Iter middle = left + (right - left) / 2;
if (*middle < val)
left = middle + 1;
else
right = middle;
}
return left;
}
...这里有一小段测试代码:
#include <iterator>
using std::end;
using std::begin;
int main() {
int a[] = {12, 20, 20, 20, 32, 40, 52};
int targets[] = {10, 19, 20, 22, 40, 60};
for (auto i : targets) {
std::cout << "Target: " << i
<< ", position: " << lower_bound(begin(a), end(a), i) - a << "\n";
}
}
另请注意,使用这种方式编写的代码,我们需要进行的唯一更改是获取upper_bound而不是lower_bound正在改变:
if (*middle < val)
left = middle + 1;
else
right = middle;
...为:
if (val < *middle)
right = middle;
else
left = middle + 1;
此代码在迭代器方面有效,因此它将迭代器返回到您可以插入指定值的位置,并且值将保持有序,并且它将是具有该值的第一个项目。如果它小于集合中的任何值,它将把迭代器返回到第一个项目。如果它大于集合中的任何项目,它将返回collection.end()(它刚刚超过最后一项)。