简体   繁体   中英

How do i find the index of the number in a divide and conquer binary search?

I can use the divide and conquer binary search to find the number i want but how can i find the index of the number in the original array without using for loop and indexOf?

function search(array, value) {

    var midpoint = Math.floor(array.length / 2)

    if (value > array[midpoint]) {
        var slicedArray = array.slice(midpoint)
    } else {
        var slicedArray = array.slice(0,midpoint)
    }
    return slicedArray[Math.floor((slicedArray.length/2))] === value ? value : search(slicedArray, value)
}

console.log(search([1,3,16,22,31,33,34], 34))

You can and should condense this code substantially, but I've left it in a longer form to better illustrate the concepts.

function search(array, value) {
    if (array.length == 0)
        return NaN;

    var midpoint = Math.floor(array.length / 2);

    if (array[midpoint] === value)
        return midpoint;

    if (array[midpoint] < value)
        return search(array.slice(midpoint+1),value) + midpoint + 1;

    if (array[midpoint] > value) 
        return search(array.slice(0,midpoint),value);
}

When you write a recursive function, the first two questions you should always ask yourself are "How do I know I'm done?" and "No really, is there any way this could fail to reach a completion condition?"

You want to make certain you have covered every possible state. In this case, there are four:

  • The array is empty.
  • The value at the midpoint of the array is equal to your search value.
  • The value at the midpoint of the array is less than your search value.
  • The value at the midpoint of the array is greater than your search value.

Using NaN as the 'search failed' return value is convenient because it avoids needing null-checking conditional logic around returning the value from recursion back up the chain; NaN plus a number equals NaN .

You don't need to know and shouldn't try to calculate the index of the search value in the original array at the moment you find it, several recursive calls later. It's the calling instance's job to combine what it knows (its own midpoint) with the result of the recursion and return a useful value back up the chain. In fact, no particular call to this function should 'know' whether it was the original call or a recursion. If you ever find yourself NEEDING to know the answer to that question, it's a warning flag that you should re-examine your logic.

You can have a wrapper function _binarySearch to do the actual binary search, along with taking two additional parameters l, r , whereas you can call search with just two parameters array, value

function _binarySearch(array, value, l, r) {
if (l > r) return -1;

var midPoint = Math.floor((l + r) / 2);

if (value == array[midPoint])
    return midPoint;

else if (value > array[midPoint])
    return _binarySearch(array, value, midPoint + 1, r);

else
    return _binarySearch(array, value, l, midPoint - 1);
}

function search(array, value) {
    return _binarySearch(array, value, 0, array.length);
}

If you want to know the first occurrence of an element, the worst case time complexity of the algorithm is not O(log n) anymore, it degenerates to O(n) .

This modification becomes necessary

if (value == array[midPoint]) {
    while(midPoint > -1 && array[midPoint] == value)
        --midPoint;

    return midPoint + 1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM