binary search on c, the while loop

北慕城南 提交于 2020-05-27 09:13:32

问题


There's something that I don't get with the binary search code on C.

int binarySearch(int a[], int n, int x)
{
   int low=0, mid, high=n-1;
   while(low <= high)
   {
        mid = (low + high) / 2;
        if (x < a[mid])
            high = mid - 1;
        else if (x > a[mid])
         low = mid + 1;
       else
         return mid;
   }
   return -1;
}

Why does the while loop while(left<=right) can't be written: while(left<right)? Will this change effect things?


回答1:


Take a simple case of

int a[1] = {5};
printf("%d\n", binarySearch(a, 1, 5));

With while(low < high), code prints -1 (did not find - wrong answer).

With while(low <= high), code prints 0 (found - right answer).




回答2:


Part 1 - quick answer to this specific problem

This is not a complete summary of the binary search, but I will put it in short to solve this question.
The key difference for these two while loop conditions, given
1. that the low(left) and high(right) pointers are updated accordingly. By "accordingly", please see part 3.
2. given that there is no duplicate in the boundary of LOW(LEFT) and HIGH(RIGHT)
3. given that the target exists in the array

while(low <= high) does the search in the range of [LOW, HIGH], both ends inclusive.
In comparison while(low < high) does the binary search in the range [LOW, HIGH), right/high end exclusive. For binary searches of the target in the upper/right range/part, they always miss checks at the very end/right/high, where the last low(left) stops. To make the range fully covered, one is usually recommended to make another judgement, based on the last low(left) pointer.


Part 2 - general guidelines

General guidelines that might be arbitrary:
1. when dealing with situations where the target surely exists in the array, and the array for search does not contain duplicates, while(low <= high) is preferred
2. when dealing with situations where target does not surely exist in the array, and the array might contain duplicates, while(low < high) is recommended.

Part 3 - code

low(left) and high(right) pointers updated "accordingly"

    public int binarySearch(int[] nums, int target){

        int left = 0, right = nums.length - 1;
        // please pay attention to the initial condition of right(ptr)
        while(left <= right){
            // to floor the mid
            int mid = left + (right - left) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        return -1;
    }
    public int binarySearch(int[] nums, int target){
        // please pay attention to the initial condition or the right(ptr)
        int left = 0, right = nums.length;

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

            // please pay twice attention to the equality case
            if(target > nums[mid]) {
                left = mid + 1;
             } else {
                right = mid;
             }
        }

        return left;
    }

Part 4 - Variations, slightly more advanced

Warning: Confusions might be caused
for the type of while(low <= high):

    public int binarySearchWithFlooringMid(int[] nums, int target){
        // please pay attention to the initial condition of right(ptr)
        int left = 0, right = nums.length - 1;
        while(left <= right){
            // to floor the mid
            int mid = left + (right - left) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        return -1;
    }

    public int binarySearchWithCeilingMid(int[] nums, int target){
        int left = 0, right = nums.length - 1;
        while(left <= right){
            // to ceil the mid
            int mid = left + (right - left + 1) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }

        return -1;
    }

For the type of while(low < high)

    public int binarySearchLeftmost(int[] nums, int target){
        int left = 0, right = nums.length;

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

            // please pay twice attention to the equality case
            if(target > nums[mid]) {
                left = mid + 1;
             } else {
                 right = mid;
             }
        }

        return left;
    }

    public int binarySearchRightmost(int[] nums, int target){
        int left = 0, right = nums.length;

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

            // please pay twice attention to the equality case
            if(target < nums[mid]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }

        return right - 1;
    }

This post does NOT cover all the cases in terms of binary searches. There are much more sophisticated requirements, which I will talk about in more details after mastering them.



来源:https://stackoverflow.com/questions/35798622/binary-search-on-c-the-while-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!