[Binary Search] Prototypes and variants and related thinking

1. The words written in front

When the author met a very NB Internet company, I was faced with a variant of binary search. After I came back, I thought deeply about this seemingly simple binary search. It may not be in-depth, but at least I learned it more than before. terrific. Every interview will bring different thinking inspiration. After meeting this company, the biggest inspiration for me is that learning algorithm is not only learning itself, but also should see its boundaries and scalability, and often think about these good classic algorithms , let it be integrated into your subconscious, only then can you truly master it. Without further ado, let's get started.

2. Binary Search Prototype

/***********************************************
Author:tmw
date:2018-3-24
************************************************/  
#include <stdio.h>  
#include <stdlib.h>  
  
/**Binary search**/  
int binary_search(int array[] , int array_number , int target_data )  
{  
    int left = 0;  
    int right = array_number - 1;  
  
    while(left<=right)  
    {  
        int mid = left + ( right - left ) / 2;  
  
        if( target_data > array[mid] ) //The target value is greater than the middle value, it means that the middle value is searched to the right--change the left value  
            left = mid + 1;  
        else if( target_data < array[mid]) //The target value is less than the middle value, indicating that the middle value is searched on the left--change the right value  
            right = mid - 1;  
        else  
            return mid;  
    }  
    return -1; // if not found, return -1  
}  

The premise of the binary search prototype code is: 1. The array is ordered; 2. Repeated elements are not considered

Binary search time complexity O(logn), space complexity O(1)

Therefore, when these two conditions change, it is necessary to make some small changes on the basis of the original binary search.

3. Binary search variant 1 ----- Repeated elements appear

[For example] In an ordered array, find a number k, find its first occurrence position and last occurrence position in the array, there may be duplicate elements in the array.

    This question has confirmed that the array is an increasing sequence, so in binary search, only the processing of duplicate elements
needs to be considered The position of the first occurrence) or explore backward (find the position of the last occurrence)
    Therefore,
        1) In finding the position of the first occurrence, when array[mid] == target, because of uncertainty array[mid- 1]?=array[mid], so don't just return mid at will, but use a variable to temporarily store the mid value, let right=mid-1 (the outer while loop left<=right, must take the equal sign is right=mid-1, if the equal sign is not taken, it is right=mid)

        2) When looking for the position of the last occurrence, when array[mid] == target, because you are not sure about array[mid+1]?=array[mid], don't just return mid at will, but also use a variable first Temporarily store the mid value, let left=mid+1 (the outer while loop left<=right, must take the equal sign to be left=mid+1, if not take the equal sign, left=mid)

code show as below:

/*************************************************
Author:tmw
date:2018-3-24
*************************************************/
#include <stdio.h>
#include <stdlib.h>

/**
variant:
1. The sequence increment condition remains unchanged
2. Elements may be repeated—changes
**/

/**Find the upper bound**/
int Binary_find_FirstPosition(int* array, int len, int target)
{
    int left = 0;
    int right = len-1;
    int years = -1;
    while( left<=right )
    {
        int mid = left+(right-left)/2;
        if( target == array[mid] )
        {
            ans = mid;
            /**
                Since the above while loop takes the equal sign, when looking for the first occurrence, use:
                right = mid-1;
            **/
            right = mid-1;
        }
        else if( target > array[mid] )
            left = mid + 1;
        else
            right = mid - 1;
    }
    return ans;
}

int Binary_find_LastPosition(int* array, int len, int target)
{
    int left = 0;
    int right = len-1;
    int years = -1;
    while( left <= right )
    {
        int mid = left + (right-left)/2;
        if( target == array[mid] )
        {
            ans = mid;
            /**
                Since the above while loop takes the equal sign, when looking for the last occurrence, use:
                left = mid+1;
            **/
            left = mid + 1;
        }
        else if( target > array[mid] )
            left = mid + 1;
        else
            right = mid - 1;
    }
    return ans;
}

4. Binary search variant 2 ---- Rotate the sorted array, mid segmentation makes one part ordered and the other unordered

[Example] Search for the target value target in a rotated sorted array, if it is found in the array, return its index, otherwise return -1. Array elements are not repeated

This problem is different from the normal sorted sequence because it is rotated sorted 4 5 6 7 0 1 2. The binary search is still used, but the boundary needs to be improved:

1. When the position of mid is cut to the interior or edge of the left part of the array

    1) If the target value is on the left, the left must be monotonically increasing, that is, array[left]<=target<array[mid], let the right cursor be placed at mid

    2) If the target value is on the right, the right side is not necessarily monotonically increasing, and the left cursor is placed at mid+1 to continue watching.

2. When the position of mid is cut to the inside of the right part

    1) If the target value is on the right: the right side must be monotonically increasing, that is, array[right]>=target>array[mid], let left = mid+1

    2) If the target value is on the left, the left does not necessarily increase monotonically, and the right cursor is placed in the mid to continue watching.

/*************************************************
Author:tmw
date:2018-3-23
*************************************************/
#include <stdio.h>
#include <stdlib.h>

/**

Binary search variant:
1. Some parts of the sequence are determined to be incremented, and some parts are not necessarily incremented----changes
2. There are no repeating elements in the sequence

**/

int search( int* array, int len, int target )
{
    int left = 0;
    int right = len-1;
    int mid;

    while( left < right )
    {
        mid = left+(right-left)/2;
        if( array[mid] == target )
            return mid;

        /**When the position of mid is cut to the inside or edge of the left part of the array**/
        if( array[left]<=array[mid] )
        {
            /**
                If the target value is on the left: the left must be monotonically increasing, that is, array[left]<=target<array[mid]
                Note: target<array[mid] does not take the equal sign because this situation is directly considered in the previous if.
            **/
            if( target<array[mid] && target>=array[left])
                right = mid;
            /**target value on the right side**/
            else
                left = mid+1;
        }
        /**When the position of mid is cut to the inside of the right part**/
        else
        {
            /**
                If the target value is on the right: the right must be monotonically increasing, that is, array[right]>=target>array[mid]
            **/
            if( array[right]>=target && target>array[mid] )
                left = mid+1;
            else
                right = mid;
        }
    }
    return -1; // not found
}

5. Binary search variant 3 ---- Rotate the sorted array, mid segmentation makes one part ordered and the other unordered, and there are duplicate elements at the same time

[Example] Search for the target value target in a rotated sorted array, if it is found in the array, return its index, otherwise return -1. Array elements allow repetition

    Repeated elements are allowed. If array[mid]>=array[left] in the previous question, then the assumption that [left,mid] is an increasing sequence cannot be established, such as [1,3,1,1,1].

    If array[mid]>=array[left] cannot be determined to increment, split it into two conditions:

        1) If array[mid]>array[left], the interval [left,mid] must increase

        2) If array[mid]==array[left] cannot be determined, it may be an indefinite increase of [1,3,1,1,1], or it may be [3,3,3,1,1] If the type is incremented, then left++, and you can look down one step.

/*************************************************
variant:
1. The sequence does not necessarily increase (related to the division of the mid position and the repetition of elements) ----- Changes
2. Elements may be repeated—changes

Author:tmw
date:2018-3-23
*************************************************/
#include <stdio.h>
#include <stdlib.h>

/**Time complexity O(logn), space complexity O(1)**/
int search_pro( int array[], int len, int key )
{
    int left = 0;
    int right = len-1;

    while( left <= right )
    {
        int mid = left+(right-left)/2;

        /**When cutting to the middle**/
        if( key == array[mid] )
            return mid;

        /**When cutting to the left part of the increasing sequence**/
        if( array[mid] > array[left] )
        {
            /**
                When the key is in the left part, the left is not necessarily a monotonically increasing sequence due to repeated elements
                For example: 3,3,3,1,1
            **/
            if( array[left]<=key && key < array[mid] )
                right=mid;
            else
                left=mid+1;
        }
        /**When cutting to the right part of the incrementing sequence**/
        else if( array[mid] < array[left] )
        {
            /**
                When the key is in the right part, the right side is not necessarily a monotonically increasing sequence due to repeated elements
                For example: 1,3,1,1,1
            **/
            if( array[mid]<key && key<=array[right] )
                left = mid+1;
            else
                right = mid;
        }
        /**
            When the cut point is such that either the left or the right side is not an increasing sequence
            Then left++ takes another step
        **/
        else
            left++;

    }
    return -1;//Not found
}

        No matter what variant is done, in binary search, it is either an increase in the judgment condition (boundary); Whether the equal sign is taken will also affect the selection of the following ifs . When using it, keep your mind awake. Don't panic, don't panic, don't panic . Say important things three times [cover your face] [cover your face] [cover your face]. . .


In the end, it's the same sentence: I still have to have a dream, in case it comes true~~~~ヾ(◍°∇°◍)ノ゙~~~


Guess you like

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