• 你真的会写二分查找吗?


    二分查找

     1 //二分查找
     2 int binarySearch(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key < arr[mid]) {//key在左边
    11             right = mid - 1;
    12         } else if (arr[mid] < key) {//key在右边
    13             left = mid + 1;
    14         } else {
    15             return mid;
    16         }
    17     }
    18     return -1;
    19 }

    二分查找变形

    随着二分查找的进行,如果找到key并不结束循环的话,最终的结束状态会是right < left,并且right + 1 = left。

    当数组中存在key时,根据二分区间选择的不同,这里又分为两种情况,如下图(key为2时),

    当数组中不存在key时,最后仅有一种情况,即把图中的黄色框框去掉。

    那么,可以找到

    1 最后一个小于key的元素,1,

    2 第一个大于等于key的元素,2,

    3 最后一个小于等于key的元素,2,

    4 第一个大于key的元素,5,

    另外,如果存在多个key时,稍加判断,就可以找到

    5 第一个与key相等的元素

    6 最后一个与key相等的元素

    1 查找最后一个小于key的元素

     1 //1 查找最后一个小于key的元素
     2 int findLastLess(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key <= arr[mid]) {
    11             right = mid - 1;
    12         } else {
    13             left = mid + 1;
    14         }
    15     }
    16     return right;
    17 }
    View Code

    2 查找第一个大于等于key的元素

     1 //2 查找第一个大于等于key的元素
     2 int findFirstGreaterEqual(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key <= arr[mid]) {
    11             right = mid - 1;
    12         }
    13         else {
    14             left = mid + 1;
    15         }
    16     }
    17     return left;
    18 }
    View Code

    3 查找最后一个小于等于key的元素

     1 //3 查找最后一个小于等于key的元素
     2 int findLastLessEqual(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key < arr[mid]) {
    11             right = mid - 1;
    12         } else {
    13             left = mid + 1;
    14         }
    15     }
    16     return right;
    17 }
    View Code

    4 查找第一个大于key的元素

     1 //4 查找第一个大于key的元素
     2 int findFirstGreater(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key < arr[mid]) {
    11             right = mid - 1;
    12         }
    13         else {
    14             left = mid + 1;
    15         }
    16     }
    17     return left;
    18 }
    View Code

    5 查找第一个与key相等的元素

     1 //5 查找第一个与key相等的元素
     2 int findFirstEqual(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key <= arr[mid]) {
    11             right = mid - 1;
    12         } else {//arr[mid] < key
    13             left = mid + 1;
    14         }
    15     }
    16     //arr[right] < key <= arr[left]
    17     //right是最后一个小于key的
    18     //left是第一个大于等于key的
    19     if (left < len && arr[left] == key) {
    20         return left;
    21     }
    22     return -1;
    23 }
    View Code

    6 查找最后一个与key相等的元素

     1 //6 查找最后一个与key相等的元素
     2 int findLastEqual(int arr[], int len, int key)
     3 {
     4     int left = 0;
     5     int right = len - 1;
     6     int mid;
     7 
     8     while (left <= right) {
     9         mid = (left + right) / 2;
    10         if (key < arr[mid]) {
    11             right = mid - 1;
    12         } else {//arr[mid] <= key
    13             left = mid + 1;
    14         }
    15     }
    16     //arr[right] <= key < arr[left]
    17     //right是最后一个小于等于key的
    18     //left是第一个大于key的
    19     if (right >= 0 && arr[right] == key) {
    20         return right;
    21     }
    22     return -1;
    23 }
    View Code

    最后补一张图,辅助理解,

    怎么记呢?

    看到其它博客的总结,也不错,

    http://www.cnblogs.com/luoxn28/p/5767571.html

    但是我觉得不够清晰好记,这里我总结为:

    只要记住上面两幅图就好了,哈哈...

    其实,只要记住比较符号和返回值,其它的代码都一样,

    1     while (left <= right) {
    2         mid = (left + right) / 2;
    3         if (key ? arr[mid]) {
    4             right = mid - 1;
    5         } else {
    6             left = mid + 1;
    7         }
    8     }
    9     return ?;

    根据要求的值的位置,先确定比较符号,再确定返回值,

    比较符号:左<=,右<

    返回值:左right,右left

    贴一个完整的测试代码吧,

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 //二分查找
      5 int binarySearch(int arr[], int len, int key)
      6 {
      7     int left = 0;
      8     int right = len - 1;
      9     int mid;
     10 
     11     while (left <= right) {
     12         mid = (left + right) / 2;
     13         if (key < arr[mid]) {//key在左边
     14             right = mid - 1;
     15         } else if (arr[mid] < key) {//key在右边
     16             left = mid + 1;
     17         } else {
     18             return mid;
     19         }
     20     }
     21     return -1;
     22 }
     23 
     24 //1 查找最后一个小于key的元素
     25 int findLastLess(int arr[], int len, int key)
     26 {
     27     int left = 0;
     28     int right = len - 1;
     29     int mid;
     30 
     31     while (left <= right) {
     32         mid = (left + right) / 2;
     33         if (key <= arr[mid]) {
     34             right = mid - 1;
     35         } else {
     36             left = mid + 1;
     37         }
     38     }
     39     return right;
     40 }
     41 
     42 //2 查找第一个大于等于key的元素
     43 int findFirstGreaterEqual(int arr[], int len, int key)
     44 {
     45     int left = 0;
     46     int right = len - 1;
     47     int mid;
     48 
     49     while (left <= right) {
     50         mid = (left + right) / 2;
     51         if (key <= arr[mid]) {
     52             right = mid - 1;
     53         }
     54         else {
     55             left = mid + 1;
     56         }
     57     }
     58     return left;
     59 }
     60 
     61 //3 查找最后一个小于等于key的元素
     62 int findLastLessEqual(int arr[], int len, int key)
     63 {
     64     int left = 0;
     65     int right = len - 1;
     66     int mid;
     67 
     68     while (left <= right) {
     69         mid = (left + right) / 2;
     70         if (key < arr[mid]) {
     71             right = mid - 1;
     72         } else {
     73             left = mid + 1;
     74         }
     75     }
     76     return right;
     77 }
     78 
     79 //4 查找第一个大于key的元素
     80 int findFirstGreater(int arr[], int len, int key)
     81 {
     82     int left = 0;
     83     int right = len - 1;
     84     int mid;
     85 
     86     while (left <= right) {
     87         mid = (left + right) / 2;
     88         if (key < arr[mid]) {
     89             right = mid - 1;
     90         }
     91         else {
     92             left = mid + 1;
     93         }
     94     }
     95     return left;
     96 }
     97 
     98 //5 查找第一个与key相等的元素
     99 int findFirstEqual(int arr[], int len, int key)
    100 {
    101     int left = 0;
    102     int right = len - 1;
    103     int mid;
    104 
    105     while (left <= right) {
    106         mid = (left + right) / 2;
    107         if (key <= arr[mid]) {
    108             right = mid - 1;
    109         } else {//arr[mid] < key
    110             left = mid + 1;
    111         }
    112     }
    113     //arr[right] < key <= arr[left]
    114     //right是最后一个小于key的
    115     //left是第一个大于等于key的
    116     if (left < len && arr[left] == key) {
    117         return left;
    118     }
    119     return -1;
    120 }
    121 
    122 //6 查找最后一个与key相等的元素
    123 int findLastEqual(int arr[], int len, int key)
    124 {
    125     int left = 0;
    126     int right = len - 1;
    127     int mid;
    128 
    129     while (left <= right) {
    130         mid = (left + right) / 2;
    131         if (key < arr[mid]) {
    132             right = mid - 1;
    133         } else {//arr[mid] <= key
    134             left = mid + 1;
    135         }
    136     }
    137     //arr[right] <= key < arr[left]
    138     //right是最后一个小于等于key的
    139     //left是第一个大于key的
    140     if (right >= 0 && arr[right] == key) {
    141         return right;
    142     }
    143     return -1;
    144 }
    145 
    146 
    147 void test()
    148 {
    149 //  int a[] = {0, 1, 2, 3, 4, 5, 6};
    150     int a[] = {0, 1, 2, 2, 2, 5, 6};
    151     int len = 7;
    152     int key = 2;
    153 
    154     int index;
    155 
    156     int i;
    157     for (i = 0; i < len; ++i) {
    158         printf("%d ", i);
    159     }
    160     printf("
    ");
    161     for (i = 0; i < len; ++i) {
    162         printf("%d ", a[i]);
    163     }
    164     printf("
    ");
    165 
    166 //    index = binarySearch(a, 10, 2);
    167     printf("%d binarySearch
    ", binarySearch(a, len, key));
    168     printf("%d findLastLess
    ", findLastLess(a, len, key));
    169     printf("%d findFirstGreaterEqual
    ", findFirstGreaterEqual(a, len, key));
    170     printf("%d findLastLessEqual
    ", findLastLessEqual(a, len, key));
    171     printf("%d findFirstGreater
    ", findFirstGreater(a, len, key));
    172     printf("%d findFirstEqual
    ", findFirstEqual(a, len, key));
    173     printf("%d findLastEqual
    ", findLastEqual(a, len, key));
    174 }
    175 
    176 int main()
    177 {
    178     test();
    179     return 0;
    180 }
    View Code
  • 相关阅读:
    Linux ps命令
    SecureCRT注册机使用方法
    微信消息的处理和应答
    微信公众号开发--开发服务器接入微信服务器
    RESTful架构
    OAuth2.0详解
    HTTP头详解
    Cookie/Session机制详解
    学习tornado:安全
    python tornado框架实现CRUD
  • 原文地址:https://www.cnblogs.com/gongpixin/p/6761389.html
Copyright © 2020-2023  润新知