二分法的关键在于对“=”的判断选取范围。例如对于目标task这样寻找:
这里选择了将mid == task 的情况放入mid > task的情况。因为最后输出的用的是l.
(就是让程序找到目标task的时候,task是大于接下来的搜索范围的,然后使l不断的增加)。当到达循环终止l == r 的时候呢l 会再一次+1从而得到task而退出循环。。
相反的,如果输出是用r,那么应将mid == task的条件归入mid < task.
--------------------------------------------------------
更新总结:
二分法两个要点:
1,判断是l = mid + 1 还是 r = mid - 1;这个可以由数列的单调性和所取值与目标值的相对大小综合判断。
2,判断最后是取下标r还是l;可以用最后的临界位置考虑,当l==r的时候。
如果此时得到的值与目标值相符且执行的是l = mid + 1,则l已经不符合,我们要的下标是r;
如果此时得到的值与目标值不相符且执行的是l = mid + 1,则r已经不符合,我们要的下标是l;
如果此时得到的值与目标值相符且执行的是r = mid - 1,则r已经不符合,我们要的下标是l.
如果此时得到的值与目标值不相符且执行的是r = mid - 1,则l已经不符合,我们要的下标是r;
----其实也就是说,我们最后取的是(我们不要的那个条件)的变量。
例子如上面代码,我们要的是mid >= task的临界,不要的是mid < task;故用l下标;
while (l <= r)
{
int mid = (l + r) / 2;
if (mid < task) l = mid + 1;
else r = mid - 1;
}
printf("%d\n", l);
这里选择了将mid == task 的情况放入mid > task的情况。因为最后输出的用的是l.
(就是让程序找到目标task的时候,task是大于接下来的搜索范围的,然后使l不断的增加)。当到达循环终止l == r 的时候呢l 会再一次+1从而得到task而退出循环。。
相反的,如果输出是用r,那么应将mid == task的条件归入mid < task.
--------------------------------------------------------
更新总结:
二分法两个要点:
1,判断是l = mid + 1 还是 r = mid - 1;这个可以由数列的单调性和所取值与目标值的相对大小综合判断。
2,判断最后是取下标r还是l;可以用最后的临界位置考虑,当l==r的时候。
如果此时得到的值与目标值相符且执行的是l = mid + 1,则l已经不符合,我们要的下标是r;
如果此时得到的值与目标值不相符且执行的是l = mid + 1,则r已经不符合,我们要的下标是l;
如果此时得到的值与目标值相符且执行的是r = mid - 1,则r已经不符合,我们要的下标是l.
如果此时得到的值与目标值不相符且执行的是r = mid - 1,则l已经不符合,我们要的下标是r;
----其实也就是说,我们最后取的是(我们不要的那个条件)的变量。
例子如上面代码,我们要的是mid >= task的临界,不要的是mid < task;故用l下标;