python Binary search It is surprisingly easy to implement bisect.bisect_left and bisect.bisect_right from 0

background

Binary search of python is usually implemented using the bisect library, but this time I tried using it from 0.

bisect.bisect_left

When calling the library


import bisect
bisect.bisect_left(arr, target)

Example of calling a library


arr = [1, 2, 3, 4, 5, 5, 5, 7, 8, 9, 9, 10]

#Where to insert target in an array, in order
target = 6
result = bisect.bisect_left(arr, target)
print("bisect_left:target not exists")
print(result)

#If targets already exist in the array, the leftmost location of the existing targets
target = 5
result = bisect.bisect_left(arr, target)
print("bisect_left:target exists")
print(result)
output:
bisect_left:target not exists
7
bisect_left:target exists
4

*** Implementation from 0 Example using bisect_left ***


from typing import List
def bisect_left(arr: List[int], target: int, left: int, right: int):
    while left < right:
        mid = (left + right) // 2
        if arr[mid] >= target: #Only here is different, please examine
            right = mid
        else:
            left = mid + 1

    return left #At this time, left and right are in the same place, so it doesn't matter which one you return.

*** Example of using implementation of bisect.bisect_left from 0 ***


#Where to insert target in an array, in order
target = 6
result = bisect_left(arr, target, 0, len(arr) - 1)
print("bisect_left:target not exists")
print(result)

#target If it already exists, the leftmost location of the existing targets
target = 5
result = bisect_left(arr, target, 0, len(arr) - 1)
print("bisect_left:target exists")
print(result)
output
bisect_left:target not exists
7
bisect_left:target exists
4

bisect.bisect_right

When calling the library


import bisect
bisect.bisect_right(arr, target)

Example of calling a library


import bisect


arr = [1, 2, 3, 4, 5, 5, 5, 7, 8, 9, 9, 10]

#Where to insert the target in the array, keeping the order
target = 3
result = bisect.bisect_right(arr, target)
print("bisect_left:target not exists")
print(result)

#target If it already exists, the rightmost location of the existing targets
target = 5
result = bisect.bisect_right(arr, target)
print("bisect_left:target exists")
print(result)

bisect_left:target not exists
3
bisect_left:target exists
7

*** Implementation of bisect.bisect_right from 0 ***


from typing import List
def bisect_right(arr:List[int],target:int,left:int,right:int)->int:
    while left < right:
        mid = (left + right) // 2

        if arr[mid] > target: #Only here is different, please examine
            right = mid
        else:
            left = mid + 1

    return left #At this time, left and right are in the same place, so it doesn't matter which one you return.

*** Example using bisect_right implemented from 0 ***


arr = [1, 2, 3, 4, 5, 5, 5, 7, 8, 9, 9, 10]

#Where to insert the target in the array, keeping the order
target = 3
result = bisect_right(arr, target,0, len(arr) - 1)
print("bisect_left:target not exists")
print(result)

#target If it already exists, the rightmost location of the existing targets
target = 5
result = bisect_right(arr, target, 0, len(arr) - 1)
print("bisect_left:target exists")
print(result)

output
bisect_left:target not exists
3
bisect_left:target exists
7

Find value

You can use the bisect_left and bisect_right index functions that should be inserted above to find the value. I have summarized three methods. If you have one value to look for, you can use either one. If there are multiple values ​​to look for, *** use the leftmost value ***, *** use the rightmost value ***, *** use the middle value *** , I summarized it for each goal.

Priority is given to the leftmost value

*** Find target, return index of target, return leftmost index if there are multiple targets, return -1 if not ***

def findXLeft(arr: List[int], target: int) -> int:
    res = bisect_left(arr, target, 0, len(arr) - 1) 
    if arr[res] == target:
        return res
    return -1

Priority is given to the middle value

*** Find target, return index of target, return index of middle target if there are multiple, return -1 if not ***


def findXCenter(arr: List[int],target: int) -> int:
    n = len(arr)
    left = 0
    right = n - 1

    while left < right:
        mid = (left + right) // 2
        if arr[mid] == target: #As soon as you find the middle value, return
            return mid

        if arr[mid] >= target: #here>When>=, Either one is ok
            right = mid
        else:
            left = mid + 1

    if arr[left] == target:
        return left

    return -1

Priority is given to the rightmost value

*** Find target, return index of target, return rightmost index if there are multiple targets, return -1 if not ***


def findXRight(arr: List[int], target: int) -> int:
    n = len(arr)
    right = n - 1
    
    res = bisect_right(arr, target, 0, len(arr) - 1)
    
    #When there is only one target
    if arr[res] == target:
        return right
    #If there are multiple targets, right and left will be the index next to the index of the rightmost target.
    if arr[max(0,res - 1)] == target:
        return res - 1
    return -1

Summary

It's confusing at first, but it's really interesting if you can understand how bisect works.

Recommended Posts

python Binary search It is surprisingly easy to implement bisect.bisect_left and bisect.bisect_right from 0
It is easy to execute SQL with Python and output the result in Excel
Read big endian binary in Python and convert it to ndarray
From Python to using MeCab (and CaboCha)
Migration from Python2 to Python3 (Python2 is rebuilt as a virtual environment and coexists)
Porting and modifying doublet-solver from python2 to python3.
Read CSV file with Python and convert it to DataFrame as it is
[python] Send the image captured from the webcam to the server and save it
How to use is and == in Python
An engineer who has noticed the emo of cryptography is trying to implement it in Python and defeat it
I tried using Google Translate from Python and it was just too easy
If you try to install Python2 pip after installing Python3 pip and it is rejected
[What is an algorithm? Introduction to Search Algorithm] ~ Python ~
Csv output from Google search with [Python]! 【Easy】
[Python] How to read data from CIFAR-10 and CIFAR-100
From easy git installation to docker startup python
An easy way to call Java from Python
Python is easy
[Introduction] I tried to implement it by myself while explaining the binary search tree.
Implement a circular expression binary search in Python. There is a comparison with a simple full search.
Perform a Twitter search from Python and try to generate sentences with Markov chains.
[Python] Convert decimal numbers to binary numbers, octal numbers, and hexadecimal numbers
[Python] This is easy! Search for tweets on Twitter
It's not easy to write Python, it's easy to write numpy and scipy
Get mail from Gmail and label it with Python3
Implement Depth-First Search (DFS) and Breadth-First Search (BFS) in python
A story that makes it easy to estimate the living area using Elasticsearch and Python
I made a server with Python socket and ssl and tried to access it from a browser
[Python / Ruby] Understanding with code How to get data from online and write it to CSV
[Python] What is a tuple? Explains how to use without tuples and how to use it with examples.
An easy way to view the time taken in Python and a smarter way to improve it
Precautions when inputting from CSV with Python and outputting to json to make it an exe
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
Binary search in Python
Binary search (python2.7) memo
[Python] Binary search ABC155D
Binary search with python
Binary search with Python3
Binary search in Python (binary search)
Easy to use Nifty Cloud API with botocore and python
Try to make it using GUI and PyQt in Python
After all it is wrong to cat with python subprocess.
Application to display and search local memos (diary) in Python
Python regular expression basics and tips to learn from scratch
How to connect to various DBs from Python (PEP 249) and SQLAlchemy
Tips for coding short and easy to read in Python
If it is not easy to understand, it cannot be improved.
[Python] I installed the game from pip and played it
How to convert Youtube to mp3 and download it super-safely [Python]
Object-oriented in C: Refactored "○ ✕ game" and ported it to Python
Go language to see and remember Part 8 Call GO language from Python
PyArmor ~ Easy way to encrypt and deliver python source code ~
Overview of Python virtual environment and how to create it
[Python] What is pip? Explain the command list and how to use it with actual examples
Read the old Gakushin DC application Word file (.doc) from Python and try to operate it.
It is surprisingly troublesome to get a list of the last login date and time of Workspaces
[Python] Although it is a humanities, I will do my best to understand bit full search
NameError: global name'dot_parser' is not defined and what to do when it comes up in python