http://blog.youkuaiyun.com/int64ago/article/details/7425727
今天求最长非递减子序列的时候,用lower—bound一直wa,百思不得其解,最后想明白不是找第一个大于等于的数,而是找到第一个大于的数。所以只能自己手写二分了,原来一直以为二分很简单,但是今天写了之后发现总是有各种小错误。比如while (left < right)和while (left <= right) 的选择,比如a[mid] > key 和a[mid] >= key 的选择。直到看到上面那篇博客,受益匪浅,不过就我今天写的题还有一些要添加的内容。
先贴出上面博客的几种情况的二分
Hint: begin是第一个元素的下标,end是最后一个元素的下标加1
YES_LEFT (如果有多个元素,返回最左边一个元素的下标)或 NO_RIGHT(如果没有,返回key可以插入位置的下一个元素下标)
int Binary_search(int begin, int end, int key)
{
int left = begin, right = end, mid;
while(left <= right)
{
mid = (left + right) >> 1;
if(num[mid] >= key)
right = mid - 1;
else left = mid + 1;
}
return left;
}
YES_RIGHT(如果有多个元素,返回最右边一个元素的下标) 或 NO_LEFT(如果没有,返回key可以插入位置的前一个元素)
int Binary_search(int begin, int end, int key)
{
int left = begin, right = end, mid;
while(left <= right)
{
mid = (left + right) >> 1;
if(num[mid] > key)
right = mid - 1;
else left = mid + 1;
}
return right;
}
但是我今天需要的并不是上面任何一种的二分,我要求的二分是,返回一个数组中第一个大于key的值的下标
int Binary_search(int begin, int end,int key)
{
int left = begin, right = end, mid;
while(left <= right)
{
mid = (left + right) >> 1;
if(num[mid] > key)
right = mid - 1;
else left = mid + 1;
}
return left;
}
那么还有最后一种二分,它的功能是找出最后一个比key值小的元素的下标,如果所有元素都大于等于key,返回0。
int Binary_search(int begin, int end, int key)
{
int left = begin, right = end, mid;
while(left <= right)
{
mid = (left + right) >> 1;
if(num[mid] >= key)
right = mid - 1;
else left = mid + 1;
}
return right;
}
上面四种代码可以实现我们想要的功能,假如我们现在想要的功能是,查找元素,如果有多个,返回最左边的下标,如果没有,返回-1。我们可以从YES_LEFT修改得出,
只要最后判断返回下标所代表的元素是不是key,就可以知道key到底存在不存在。
int Binary_search(int begin, int end, int key)
{
int left = begin, right = end, mid;
while(left <= right)
{
mid = (left + right) >> 1;
if(num[mid] >= key)
right = mid - 1;
else left = mid + 1;
}
if (num[left] == key)
return left;
else return -1;
}