二分查找

【二分查找】

二分查找是一个基础的算法,也是面试中常考的一个知识点。二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找;如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。

常规的二分查找:

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )  //不要忘记等号
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] > key)
 9             right = mid - 1;
10         else if (a[mid] < key)
11             left = mid + 1;
12         else
13             return mid;
14     }
15     return -1;
16 }

这里强调下不要忘记 left <= right 的等号   比如a[3] = {1,3,5} 我们需要查找5  如果 letf < right 的话就不会进入while循环,这会导致找不到结果

【变形一】 查找第一个与key相等的元素

因为找第一个 所以不断往左边找 所以等于号加在 right = mid-1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] >= key)
 9             right = mid - 1;
10         else if (a[mid] < key)
11             left = mid + 1;
12         }
13     if (left < n && a[left] == key)
14         return left;
15 }

【变形二】查找最后一个与key相等的元素

因为找最后一个 所以等号加在left = mid + 1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] > key)
 9             right = mid - 1;
10         else if (a[mid] <= key)
11             left = mid + 1;
12         }
13     if (right < n && a[right] == key)
14         return right;
15 }

【变形三】查找最后一个小于或等于key的元素

小于等于类似 等于  所以同样加载left = mid + 1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] > key)
 9             right = mid - 1;
10         else if (a[mid] <= key)
11             left = mid + 1;
12         }
13     return right;
14 }

【变形四】查找最后一个小于key的元素

小于的话要不断的往左边找 所以等号加在right = mid - 1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] >= key)
 9             right = mid - 1;
10         else if (a[mid] < key)
11             left = mid + 1;
12     }
13     return right;
14 }

【变形五】查找第一个等于或大于key的元素

等于或大于类似 等于   等号加在right = mid - 1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] >= key)
 9             right = mid - 1;
10         else if (a[mid] < key)
11             left = mid + 1;
12     }
13     return left;
14 }

【变形六】查找第一个大于key的元素

大于要不断往右边找 等号加在left = mid + 1

 1 int binarySearch(int a[],int n,int key)
 2 {
 3     int left = 0;
 4     int right = n-1;
 5     while (left <= right )
 6     {
 7         int mid = (left + right) / 2;
 8         if (a[mid] > key)
 9             right = mid - 1;
10         else if (a[mid] <= key)
11             left = mid + 1;
12     }
13     return left;
14 }

变形总结:

如果是找到第一个则都是返回left   如果是最后一个则返回right

如果我们要找第一个 > key 的元素或者元素的下标   可以利用    upper_bound  返回第一个大于的元素的下标; 

                                int pos = upper_bound(a,a+n,key) - a;   (默认数组a从0开始记录)

如果我们要找第一个 >= key 的元素或者元素的下标  可以利用       lower_bound返回第一个大于等于元素的下标;

                               int pos = lower_bound(a,a+n,key) - a;    (默认数组a从0开始记录)

原文地址:https://www.cnblogs.com/-Ackerman/p/11166481.html