1

Is it okay to write an implementation of the binary search in the following way?

    def binarySearching(sortedArr,v):
    if len(sortedArr)>=1:
        mid = len(sortedArr)//2
        if v<sortedArr[mid]:
            return binarySearching(sortedArr[:mid],v)
        elif v>sortedArr[mid]:
            return binarySearching(sortedArr[mid+1:],v)
        else:
            return mid
        return None

I don't understand why we need to specify low and high for the algorithm.

edit: Thanks to @Stef, this implementation isn't correct because mid is not of an original array, but of a subarray

4
  • 1
    Yes this looks correct, what made you think it might not have been? Did you test it on a list? a = [x for x in range(0, 101, 2)] b = [x for x in range(1, 100, 2)] print(all(binarySearching(a, x) for x in a)) print(any(binarySearching(a, x) for x in b)) should print "true" then "false" if your program is correct. Commented Sep 8, 2020 at 8:42
  • Sorry, the test should be instead: a = [x for x in range(0, 101, 2)] b = [x for x in range(1, 100, 2)] print(all(binarySearching(a, x) == x / 2 for x in a) and all(binarySearching(a, x) is None for x in b)) should print "true" if your program is correct. Commented Sep 8, 2020 at 8:54
  • Well, actually your implementation is incorrect. The line return mid returns the value of mid which is the position of v in the subarray you are currently searching, and not the position of v in the original array. Commented Sep 8, 2020 at 8:58
  • Apart from returning the wrong index, the rest of your code is correct; you can test that it returns an int when v is in the array and None when it isn't with isinstance: a = [x for x in range(0, 101, 2)] b = [x for x in range(1, 100, 2)] print(all(isinstance(binarySearching(a, x), int) for x in a) and all(binarySearching(a, x) is None for x in b)) Commented Sep 8, 2020 at 9:12

3 Answers 3

1

When using the binary search algorithm you each step narrows down the search area by half.

You specify low and high as you pass the same array to search and change only the search area.

The alternative to passing low and high is to pass part of the array, yet in python that means that each time you slice the array (list) you create another object (which is the sliced list) - and that is memory inefficient.

Sign up to request clarification or add additional context in comments.

Comments

1

You have to specify low and high when you work with the only array/list. At every iteration you treat a part of list in low..high range.

Your implementation makes sublists, so it does not need explicit range definition (but is this sublist formation free of cost?)

Comments

0

Compare these two implementations of binarySearch. The first is yours, the second is mine.

In your version, you are passing "slices", ie, entire copies of subarrays, to the recursive call. In my version, all recursive calls access the same array without copying it, and instead only low and high are passed as parameters.

# using slices, ie, copies of subarrays
def binarySearching(sortedArr,v):
    # print(sortedArr)
    if len(sortedArr)>=1:
        mid = len(sortedArr)//2
        if v<sortedArr[mid]:
            return binarySearching(sortedArr[:mid],v)
        elif v>sortedArr[mid]:
            return binarySearching(sortedArr[mid+1:],v)
        else:
            return mid
    else:
        return None

# using low and high indices
def otherBinarySearching(sortedArr, v):
    def auxiliary(low, high, v):
        #print(low, high, sortedArr[low:high])
        if high > low:
            mid = (high + low) // 2
            if v < sortedArr[mid]:
                return auxiliary(low, mid, v)
            elif v > sortedArr[mid]:
                return auxiliary(mid+1, high, v)
            else:
                return mid
        elif high == low:
            return (low if v == sortedArr[low] else None)
    return auxiliary(0, len(sortedArr), v)

# add some tests to make sure implementations are correct
if __name__=='__main__':
    a = [x for x in range(0, 101, 2)]
    b = [x for x in range(1, 100, 2)]
    print('a: ', a)
    print('b: ', b)
    print('binarySearching:      ', all(isinstance(binarySearching(a, x), int) for x in a) and all(binarySearching(a, x) is None for x in b))
    print('otherBinarySearching: ', all(otherBinarySearching(a, x) == x / 2 for x in a) and all(otherBinarySearching(a, x) is None for x in b))

In addition, your version returns the wrong indices: the line return mid returns the index of v in the subarray binarySearching is currently looking at, instead of the index in the original array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.