LeetCode -- binary search

Posted by micknic on Mon, 24 Jan 2022 20:34:59 +0100

Binary search

The first day of entering LeetCode, follow Code Capriccio Several questions (based on Java) for binary search are brushed on the route of. Here, we simply share the following questions and solutions.

Binary search is a comparison based algorithm. The idea is to constantly take the number of middle positions of the ordered array and compare it with the target number. If it is larger than the target number, it means that the target number is on the left of the current position (array ascending order). At this time, update the right boundary to the current position and continue to find the number of middle positions. When we implement the code, we can focus on the setting of the left and right intervals. Let's go straight to the question.

Question 1: leetcode_704

Given an n-element ordered (ascending) integer array nums and a target value target, write a function to search the target in nums. If the target value exists, return the subscript, otherwise return - 1

Example 1:

Input: nums = [-1,0,3,5,9,12], target = 9
 Output: 4
 Explanation: 9 appears in nums Middle and subscript 4

Example 2:

Input: nums = [-1,0,3,5,9,12], target = 2
 Output:-1
 Explanation: 2 does not exist nums So return -1

Tips:

  1. You can assume that all elements in nums are not repeated.

  2. n will be between [1, 10000].

  3. Each element of num will be between [- 9999, 9999].

Problem solving ideas:

Beginners must think of traversing from beginning to end at the beginning, but if the array is very long, it will take a lot of time. Professionally speaking, it is a large complexity of the algorithm. From the title, we can see that the array is in ascending order and does not repeat, which is in line with the conditions of binary search. Don't say much, knock:

public static void main(String[] args) {
    int[] nums = new int[]{-1, 0, 3, 6, 7, 8, 10, 11, 12, 14, 15};
    int target = 15;
    int result = binarySearch(nums, target);
    if (result != -1){
        System.out.println(String.format("Successfully found with subscript%d", result));
    }
    else {
        System.out.println(String.format("%d non-existent nums in", target));
    }
}

// Here is the part for leetcode submission. In main, it is used for idea to run by itself
private static int binarySearch(int[] nums, int target) {
    // Binary basic operation, initializing the left and right subscripts and the subscripts in the middle. Of course, M can also be written in the loop so far
    int L = 0, M = nums.length / 2, R = nums.length;
    while (L < R){ // Whether l < R or l < = R depends on personal habits and specific topics. Just pay attention to the change of R in the right boundary
        if (nums[M] > target)
            R = M;
        else if (nums[M] < target)
            L = M + 1;
        else
            return M;

        M = (L + R) / 2;
    }
    return -1;
}

Similar questions: leetcode_35 search insertion position , you can also use bisection. You need to change the return value.

Question 2: leetcode_69

Give you a nonnegative integer x, calculate and return the arithmetic square root of X. Since the return type is an integer, only the integer part will be retained and the decimal part will be rounded off.

Note: it is not allowed to use any built-in exponential functions and operators, such as pow(x, 0.5) or x ** 0.5

Example 1:

Input: x = 4
 Output: 2

Example 2:

Input: x = 8
 Output: 2
 Explanation: the arithmetic square root of 8 is 2.82842..., Since the return type is an integer, the decimal part will be rounded off

Tips:

  • $0 <= x <= 2^{31} - 1$

Problem solving ideas:

This question doesn't directly tell you what ordered array there is, but can we think of an integer array such as 0-x and find a number from it so that its square is equal to or just less than x? In this way, we can solve it with dichotomy. For the if judgment condition in the while loop, change the square of the current number to compare with X, that is: $m * m < x$ Upper Code:

private static int mySqrt(int x) {
    int L = 0, R = x; //Still initialize the left and right boundaries
    int ans = -1;
    while(L <= R){ //Note that the method of < = must be used here, that is, the right boundary must be equal to x, because it is not used as a subscript, but the specific number involved in the calculation. After R is changed, it is still possible to participate in the calculation
        int M = (L + R) / 2;
        if ((long) M * M > x) // When the number is too large, its square may exceed the int range, so it needs to be converted to long
            R = M - 1;
        else{
            ans = M;
            L = M + 1;
        }
    }
    return ans;
}

Similar questions: leetcode_367 effective complete square , the idea of solving the problem is the same, with an additional judgment on whether it is a complete square.

Question 3: leetcode_34 find the first and last positions of elements in a sorted array

Given an integer array nums arranged in ascending order and a target value target. Find the start and end positions of the given target value in the array. If the target value target does not exist in the array, return [- 1, - 1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
 Output:[3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
 Output:[-1,-1]

Example 3:

Input: nums = [], target = 0
 Output:[-1,-1]

Tips:

  • $0<=nums.length<=10^5$
  • $-109<=nums[i]<=109$
  • $num $is a non decreasing group
  • $-109<=target<=109$

Problem solving ideas:

The array is still non decreasing, that is, we need to find the first subscript equal to target and the last subscript equal to target. We have done two bisections twice. I don't think we will continue to search violently. How to solve it with dichotomy? You can write two functions to find the left boundary first and then the right boundary. For this, Code Capriccio A detailed explanation is also made in leetcode( Click here to view )Then, the official also gives the method of combining the two into one. See the official solution of this question for details. The following code (yes, the official handling):

// idea test
public static void main(String[] args) {
    int[] nums = new int[]{2,2};
    int target = 2;
    int[] result = searchRange(nums, target);
    System.out.println(String.format("[%d,%d]",result[0],result[1]));
}

private static int[] searchRange(int[] nums, int target) {
    int [] result;
    int leftIdx = binarySearch(nums, target, true);
    //The obtained right boundary needs - 1 because the first is greater than and not the last is equal to
    int rightIdx = binarySearch(nums, target, false) - 1;
    // Judge the obtained left and right boundaries
    if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target)
        result = new int[]{leftIdx,rightIdx};
    else
        result = new int[]{-1, -1};

    return result;
}
// Binary gets the subscript. boolean is used to distinguish whether it is a left boundary or a right boundary
private static int binarySearch(int[] nums, int target, boolean b) {
    int L = 0, R = nums.length;
    int res = nums.length;
    while (L < R){
        int M = L + ((R - L) >> 2);
        //The first condition is to find the first numerical subscript greater than target, that is, the right boundary; The second is to find the first numerical subscript equal to target, that is, the left boundary. Since there may be no numerical value equal to target, it can be combined with '> ='
        if (nums[M] > target || (b && nums[M] >= target)){
            R = M;
            res = M;
        }
        else {
            L = M + 1;
        }
    }
    return res;
}

Summary:

The above is the questions brushed on the first day of entering the pit leetcode. I also began to learn to summarize in an up master( Day up sharp Video recommendation is made by choosing code caprice (official account of WeChat public number) as the reference of javaSe and algorithm learning consolidation. In addition, the brushed questions also need to be reviewed and consolidated. Beginners can follow them and understand them into their own ideas. Finally, they can knock blindly by themselves.

The above is Xiaobian's learning and sharing of binary search. I hope you can keep summarizing and keep learning.