About binary search

Reprinted from: http://www.cnblogs.com/luoxn28/p/5767571.html
Recently, I was working on binary answers, and I found such an article explaining binary search. I feel that the posture level is very high, so I reprinted such an article.
The content of the text is as follows:
1 Binary search
  Binary search is a basic algorithm and a knowledge point that is often tested in interviews. Binary search is to compare the searched key with the middle key of the subarray. If the searched key is smaller than the middle key, continue searching in the left subarray; if it is greater than the middle key, search in the right subarray, otherwise the middle key is to be element to find.

(The picture comes from "Algorithms - 4th Edition")

/**
 - 二分查找,找到该值在数组中的下标,否则为-1
 */
static int binarySerach(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] == key) {
            return mid;
        }
        else if (array[mid] < key) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }

    return -1;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

  Every time you move the left and right pointers, you need to add +1 or -1 to mid to prevent an infinite loop, and the program can run correctly.
  Note: The judgment condition in the code must be while (left <= right), otherwise the judgment condition is incomplete, for example: array[3] = {1, 3, 5}; the key to be searched is 5, at this time in ( It will not be found under the condition of low < high), because when low and high are equal, it points to element 5, but the condition is not established at this time, and it does not enter while().
2 Variants
  of binary search For binary search, if the conditions are slightly changed, for example, the data in the array may be repeated, and the minimum (or maximum) subscript of the matching data is required to be returned; one step further, it is necessary to find out what is in the array The index of the first element greater than key (that is, the smallest element greater than key), and so on. These, although only a little changed, do need to be more careful when implementing them.
  The variant of binary search is the same as the principle of binary search. The main thing is to transform the judgment conditions (that is, the boundary conditions). If you want to see the tips on how to remember these variants, please turn to the end of this article. Let's look at the code for several binary search variants:

  • 2.1 Find the first element equal to key

      Find the first equal element, that is to say, there are many elements equal to the search key value, and return the subscript of the leftmost element of these elements.

// 查找第一个相等的元素
static int findFirstEqual(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] >= key) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    if (left < array.length && array[left] == key) {
        return left;
    }

    return -1;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 2.2 Find the last element equal to key

      Find the last equal element, that is to say, there are many elements equal to the search key value, and return the subscript of the rightmost element of these elements.

// 查找最后一个相等的元素
static int findLastEqual(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] <= key) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    if (right >= 0 && array[right] == key) {
        return right;
    }

    return -1;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 2.3 Find the last element equal to or less than key

      Find the last element equal to or less than the key, that is to say, there are many elements equal to the key value, and return the subscript of the rightmost element of these elements; if there is no element equal to the key value, return the rightmost element less than the key. mark.


// 查找最后一个等于或者小于key的元素
static int findLastEqualSmaller(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] > key) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return right;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 2.4 Find the last element less than key

      Find the last element less than key, that is, return the index of the rightmost element less than key.

// 查找最后一个小于key的元素
static int findLastSmaller(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] >= key) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return right;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 2.5 Find the first element equal to or greater than key

      Find the first element equal to or greater than the key, that is to say, there are many elements equal to the key value, return the subscript of the leftmost element of these elements; if there is no element equal to the key value, return the leftmost element greater than the key subscript.

// 查找第一个等于或者大于key的元素
static int findFirstEqualLarger(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] >= key) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return left;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 2.6 Find the first element greater than key

      Find the first element equal to key, that is, return the index of the leftmost element greater than key.

// 查找第一个大于key的元素
static int findFirstLarger(int[] array, int key) {
    int left = 0;
    int right = array.length - 1;

    // 这里必须是 <=
    while (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] > key) {
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return left;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3 Summary of binary search variants

// 这里必须是 <=
while (left <= right) {
    int mid = (left + right) / 2;
    if (array[mid] ? key) {
        //... right = mid - 1;
    }
    else {
        // ... left = mid + 1;
    }
}
return xxx;
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

  There are many variants of binary search, but their "routines" are the same. The above code is its routine. How to quickly write binary search code, just follow the steps below:

1 First determine whether to return left or right

  Because we know that the final jump out of the while (left <= right) loop condition is right < left, and right = left - 1. Finally, right and left must be stuck on the left and right sides of the "boundary value". If the comparison value is the key, find the element that is less than or equal to (or less than) the key, and the boundary value is the leftmost one of all elements equal to the key. In fact, should return left.

  Taking the array {1, 2, 3, 3, 4, 5} as an example, if we need to find the subscript of the first element that is equal to or less than 3, and the key value we compare is 3, then the last left and right must meet the following conditions :

  The key value we are comparing is 3, so at this point we need to return left.

2 Determine the comparison symbol

int mid = (left + right) / 2;
if (array[mid] ? key) {
    //... right = xxx;
}
else {
    // ... left = xxx;
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  That is, the judgment symbol in if (array[mid] ? key) here, combined with step 1 and the conditions given, if you are looking for elements less than or equal to key, you know that you should use the judgment symbol >=, because it is to return left , so if array[mid] is equal to or greater than key, you should use >=, the following is the complete code

// 查找小于等于key的元素
int mid = (left + right) / 2;
if (array[mid] >= key) {
    right = mid - 1;
}
else {
    left = mid + 1;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

refer to:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324741209&siteId=291194637