A note on dichotomy

It doesn't matter how many ways there are dichotomies,

The important thing is to be able to write the right one.

 

First a few numbers to note

There are two medians,

  1. Lower median = (length --2) / 2
  2. Upper median: upperMedian = length / 2

Commonly used is the lower median. The common writing method is as follows. The language int is often automatically rounded down.

median = (length - 1) / 2

The interval of the pointer can of course be open, closed, or half-open and half-closed. But honestly, it is always not wrong to take the closed interval at both ends. The above median, converted into two closed intervals [low, high] , becomes the following:

median = low + (high - low) / 2

There is also a common pit here, don't try to use addition quickly, it will overflow,

median = ( low + high ) / 2 // OVERFLOW

 

Another key point is the "terminal condition" .

Don't use low == high as a termination condition. will be skipped,

if (low == high) { 
    return (nums[low] >= target)? low : ++low;
}

 

Don't believe in trying to find 0 in [1, 5]?

 

The correct termination condition is:

low > high

That is, the search space is empty.

 

After the termination condition is met, the return value does not need to be tangled at all, and directly returns the low low .

Because going back and slowing down the camera, the process of binary search is a process of maintaining low :

low starts from 0. Only advance when the median encounters a certain number less than the target number, and never retreat. Low has been approaching the position of the first target number. know that it will eventually arrive.

As for the high bit, you can reduce the space of the target array with confidence and boldness.

 

So the final code is very simple,

public int binarySearch(int[] nums, int target) {
    int low = 0, high = nums.length-1;
    while (low <= high) { 
        int mid = low + (high - low) / 2;
        if (nums[mid] < target) { low = mid + 1; }
        if (nums[mid] > target) { high = mid - 1; }
        if (nums[mid] == target) { return mid; }
    }
    return low;
}

 

 

The recursive version is just as simple,

public int binarySearchRecur(int[] nums, int target, int low, int high) {
    if (low > high) { return low; } //base case
    int mid = low + (high - low) / 2;
    if (nums[mid] > target) {
        return binarySearchRecur(nums,target,low,mid-1);
    }  else if (nums[mid] < target) {
        return binarySearchRecur(nums,target,mid+1,high);
    } else {
        return mid;
    }
}

 

But the above code works fine, with one precondition:

Element space has no duplicate values

Generalizing to spaces with repeated elements , the binary search problem becomes:

Finds where the element first appears.

It can also be understood as another problem in disguise, corresponding to the lower_bound() function of C++

Find the first element position greater than or equal to the target value.

 

But as long as you master the above-mentioned binary search method, the code is simpler.

public int firstOccurrence(int[] nums, int target) {
    int low = 0, high = nums.length-1;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (nums[mid] < target) { low = mid + 1; }
        if (nums[mid] >= target) { high = mid - 1; }
    }
    return low;
}

 

 

The same goes for the recursive translation,

public int firstOccurrenceRecur(int[] nums, int target, int low, int high) {
    if (low > high) { return low; }
    int mid = low + (high - low) / 2;
    if (nums[mid] < target) {
        return firstOccurrenceRecur(nums,target,mid + 1,high);
    } else {
        return firstOccurrenceRecur(nums,target,low,mid-1);
    }
}

 

The above codes have passed the leetcode test. Standard silver bullet. Get up every morning to write and build your muscles.

 

Finally, I want to say, don't be afraid that binary search is difficult to write, and the boundary conditions are complicated. The actual situation is that you feel irritable, and Daniel has also been irritable because of these. Below some notorious questions, there are often comments of various big names (disgusting, perverted, F***, etc.). And this does not test any logical ability, it is just a careful deduction. Get a pen out and write, it's not ashamed to do the math. After a lot of problems are thoroughly clarified, they are often suddenly enlightened, and then they will make inferences from other facts in the future. above.

Guess you like

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