二分法, 二分排序

二分法, 二分排序
原文:https://blog.csdn.net/xr_acmer/article/details/18449667?utm_source=copy
感觉二分法中比较难以把握的就是一个边界问题,有的时候很可能因为考虑不好到底是取上确界还是下确界的问题,就会WA。

先看二分法的标准形式吧

int bisearch(int x, int v[], int n)
{
int low = 0, high = n - 1, mid;
while(low <= high)
{
mid = (low + high) / 2;
if(x < v[mid])
high = mid - 1;
else if(x > v[mid])
low = mid + 1;
else
return mid;
}
return -1;
}

这是 二分法的最标准的形式,二分法其实就是二分查找,一些排序算法以及在一个区间

内求解的时候,查找可能很慢,那么这时候用二分法会大大减少查找的时间。对一个序列应用二分法,那么这个序列必须要保证是有序的,不然的话不能用二分法。而且,二分法的一个性质就是,你要查找 这个问题的界一定在Low , high这两个边界之中来确定的。标准的二分法在做题目的时候有很多变形,最重要的一个 就是while循环外面的那个 return,标准的二分法这里是代表没有解,因为再循环内查找过后没有找到相应的解,所以应该返回一个无解的标志。但是在题目中往往不是这样,比如XMU果汁那道题目,题目意思是,先满足我要和多少果汁的这个前提,然后在此基础之上在少买。

如果当n == 3 x == 3的时候,那么我如果买了三瓶,实际上我可以喝四瓶,看起来并不符合条件,实际上我只需要和三瓶。但是仔细一想就会发现,如果想喝三瓶就必须去买三瓶,也就是说n == 3 x== 3也是有解的,因为我们要先满足能喝到N瓶再去看看有没有少买几瓶也能喝到N瓶的方案,所以,在二分的过程中1–3区间内并没有找到合适的解,此时,为了满足喝n瓶的条件,只能取上确界3来满足条件。实际上,这个题目的中心意思也就是找在1–3区间内能喝到n瓶所购买的最小瓶数。

int f(int n, int x)
{
if(n == 1 || x == 1)
return 1;
else{
int low = 1, high = n, mid;
while(low + 1 < high ){
mid = (low + high) / 2;
int real = cal(mid, x);
if(real == n)
return mid;
else if(real < n)
low = mid;
else
high = mid;
}
return high;
}
}

另一个题目是HDU的1157,给一个序列,排序之后找中间数,两边分别是大于等于 他的和小于等于他的数。

排序的方法是用最简单的插入排序和 二分查找结合起来。用二分查找在已经排好序的序列里面找到合适的位置将当前的数字插入进去。这里面要处理的就是没有找到合适位置的情况。当low > high说明,要插入的这个数字还要比High这个位置的数字大,所以要返回high,因为此时low已经+1,所以此时low == high,为了统一,都返回low,当high > low的时候,说明要插入的这个数字比low位置上的数字要小,自然要返回low。

所以这个题目应用而二分法的时候要返回下确界。

总之,二分法while循环之外的return 是返回没有解的情况,具体的就要根据题目的要求来对边界的情况进行考虑~

猜你喜欢

转载自blog.csdn.net/sx_huangying/article/details/83034083