转载请注明出处,谢谢:
http://blog.csdn.NET/u014285517/article/details/45341741
说真的自己开始也认为二分查找实在太简单了,不屑一顾,可是上礼拜阿里实习面试真是教会我做人要踏实啊!上礼拜面试的事等下有时间再写一篇文章细谈,现在谈谈二分查找,建议大家先自己写写,然后再看下面的文章,效果更好。
让我们先看看一个朴素版的二分查找(其实也不算太朴素,不过因为这部分网上以及编程之美里都有详细描述以及代码实现,所以也就显得比较朴素了,注意事项会在代码注释里说明):
-
-
-
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i <= j) {
-
-
-
-
-
- mid = i+(j-i>>1);
- if(a[mid] == t) {
- return mid;
- } else {
- if(a[mid] > t) {
- j = mid-1;
- } else {
- i = mid+1;
- }
- }
- }
- return -1;
- }
-
- int main() {
- int a[10] = {1,3,5,6,7,8,9,12,13,14};
- int t;
- if((t = binarySearch(a,0,9,7)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
上面的代码还有什么问题呢?大家可以先想想,再往下看哈。
显然如果要查找的数在数组中存在着重复元素,而且我们还想返回该数的最小或最大下标,显然上面的程序是无法做到的,因为它一旦找到一个满足的就退出了。
下面我们来想想怎么解决这个问题。 最容易想到的办法就是在数组中找到某一个数后,直接不断循环减(加),来寻找满足条件的最小下标(最大下标)。相应代码如下:
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i <= j) {
- mid = i+(j-i>>1);
- if(a[mid] == t) {
- while(a[--mid] == t) {
-
- }
- return mid+1;
- } else {
- if(a[mid] > t) {
- j = mid-1;
- } else {
- i = mid+1;
- }
- }
- }
- return -1;
- }
-
- int main() {
- int a[10] = {1,3,5,9,9,9,9,12,13,14};
- int t;
- if((t = binarySearch(a,0,9,9)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
现在可以想想上面的代码存在什么问题吗?
显然如果重复的元素过多,二分查找搞不好就直接退化成暴力查找了,所以是不太好的。大家可以自己先写写解决代码。
然后后看下面代码:
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i < j) {
- mid = i+(j-i>>1);
- if(a[mid] >= t) {
- j = mid;
- } else {
- i = mid+1;
- }
- }
- if(a[i] == t) {
- return i;
- } else {
- return -1;
- }
- }
-
- int main() {
- int a[10] = {1,3,9,9,9,9,9,9,13,14};
- int t;
- if((t = binarySearch(a,0,9,9)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
下面代码是找最大下标的:
-
-
-
-
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i < j) {
- mid = i+(j-i+1>>1);
- if(t >= a[mid]) {
- i = mid;
- } else {
- j = mid-1;
- }
- }
- if(a[i] == t) {
- return i;
- } else {
- return -1;
- }
- }
-
- int main() {
- int a[10] = {1,9,9,9,9,9,9,12,13,14};
- int t;
- if((t = binarySearch(a,0,9,9)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
下面我们再来思考两个类似问题,加深理解。
在一个非递减数组中(就是数组中可能存在相等的元素),求最小的下标i,使得a[i] > t,存在返回下标i,不存在返回-1。
实现代码如下:
-
-
-
-
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i < j) {
- mid = i+(j-i>>1);
- if(t >= a[mid]) {
- i = mid+1;
- } else {
- j = mid;
- }
- }
- if(a[i] > t) {
- return i;
- } else {
- return -1;
- }
- }
-
- int main() {
- int a[10] = {1,9,9,9,9,9,9,12,13,14};
- int t;
- if((t = binarySearch(a,0,9,8)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
另一个类似问题:
在一个非递减数组中(就是数组中可能存在相等的元素),求最大的下标i,使得a[i] < t,存在返回下标i,不存在返回-1。
实现代码如下:
-
-
-
-
- #include<stdio.h>
-
- int binarySearch(int a[],int s,int e,int t) {
- int i = s,j = e,mid;
- while(i < j) {
- mid = i+(j-i+1>>1);
- </span> if(t <= a[mid]) {
- j = mid-1;
- } else {
- i = mid;
- }
- }
- if(a[i] < t) {
- return i;
- } else {
- return -1;
- }
- }
-
- int main() {
- int a[10] = {1,9,9,9,9,9,9,12,13,14};
- int t;
- if((t = binarySearch(a,0,9,10)) == -1) {
- printf("不存在\n");
- } else {
- printf("存在,下标为%d\n",t);
- }
- }
如果把上面两个问题改成下面这样:
1.在一个非递减数组中(就是数组中存在相等的元素),求最**大**的下标i,使得a[i] **>** t,存在返回下标i,不存在返回-1。
2.在一个非递减数组中(就是数组中存在相等的元素),求最**小**的下标i,使得a[i] **<** t,存在返回下标i,不存在返回-1。
大家稍微想下应该能发现这种问题意义不大,我这里就不细说了。
注:上面代码都是自己写的,如果有bug欢迎指出。上面说的一些问题如果有错误也欢迎指出,谢谢。
补充Java写的一个递归实现代码:
-
- public void binarySearch(int[] a, int x, int beginIndex, int endIndex) {
- int len = endIndex - beginIndex + 1;
- if (endIndex < beginIndex) {
- System.out.println("not find");
- return;
- }
- if (a[beginIndex + len / 2] == x) {
- System.out.println("find index is:" + (beginIndex + len / 2));
- return;
- } else {
- if (x > a[beginIndex + len / 2]) {
- binarySearch(a, x, beginIndex + len / 2 + 1, endIndex);
- } else {
- binarySearch(a, x, beginIndex, beginIndex + len / 2 - 1);
- }
- }
- }