Array topic two-part search

Keywords: Algorithm leetcode

array

Binary search

704. Two point search - LeetCode (LeetCode CN. Com)

Solution:

class Solution {
    public int search(int[] nums, int target) {
        int mid;
        int left = 0, right = nums.length-1;
        while (left <= right){
           // mid = (left + right) / 2;
            mid = left + ((right-left) / 2);//Overflow can be prevented
            if (nums[mid] == target){
                return mid;
            }
            else if (nums[mid] > target){
                right = mid-1;
            }
            else if(nums[mid] < target){
                left = mid+1;
            }
        } 
        return -1;
    }
}

Features: the array is ordered and not repeated.

Difficulty: determine the interval and realize the difference between the initial state left=0,right=length and the initial state left=0 and right=length-1.

35. Search insertion position - LeetCode (LeetCode CN. Com)

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length-1;
        int mid = left;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (nums[mid] == target)
                return mid;
            else if(nums[mid] < target)
                left = mid + 1;
            else
                right = mid - 1;
        }
       /* if (nums[mid] > target)  
            return mid;
        else
            return mid + 1;*/
        //According to the judgment conditions of if, the value on the left of left is always less than target, and the value on the right of right is always greater than or equal to target, and left must eventually be equal to right+1. In this way, after the loop ends, draw a vertical line between left and right, which can just divide the array into two parts: the left part and the right part, Moreover, the left part of the left is all smaller than the target and ends with right; All the parts on the right of right are greater than or equal to target, and left is the first. So the final answer must be left
        
    }
}

34. Find the first and last position of the element in the sorted array - LeetCode (LeetCode CN. Com)

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        int mid = left,flag = -1;
        int loc[] = new int[2];
        loc[0] = -1;
        loc[1] = -1;
        while (left <= right) {
            mid = left + (right-left) / 2;
            if (nums[mid] == target){
                flag = 0;
                break;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
            else
                left = mid + 1;
        }
        if(flag == 0) {
            loc[0] = mid;
            loc[1] = mid;
            while (  loc[0] >= 0&&nums[loc[0]] == nums[mid]){
                loc[0]--;
            }
            loc[0]++;
            while (  loc[1] <= nums.length - 1&&nums[loc[1]] == nums[mid]){
                loc[1]++;
            }
            loc[1]--;
        }
        return loc;
    }
}

In my original solution, I first use bisection to find the position of a target, and then read forward and backward to find the starting point and ending point I want.

However, in fact, there is another method after knowing enough about dichotomy.

For example:

[1, 3, 4, 4, 4, 5, 6]
 0  1  2  3  4  5  6

It can be seen intuitively that the results we need to find are 2 and 4 respectively. Then we can take 2 and 4 as the subscripts we need to find.

The core of this algorithm is to search again in the left or right section of the found results.

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        int mid = left,flag = -1;
        int loc[] = new int[2];
        loc[0] = -1;
        loc[1] = -1;
        while (left <= right) {
            mid = left + (right-left) / 2;
          if(nums[mid] > target) {
              right = mid - 1;
          }
          else if (nums[mid] < target) {
              left = mid + 1;
          }
          else 
          {
              loc[0] = mid;
              right = mid - 1;
          }
        }
        left = 0;
        right = nums.length - 1;
        while (left <= right) {
            mid = left + (right-left) / 2;
          if(nums[mid] > target) {
              right = mid - 1;
          }
          else if (nums[mid] < target) {
              left = mid + 1;
          }
          else 
          {
              loc[1] = mid;
              left = mid + 1;
          }
        }
        return loc;
    }
}

The advantage of this improvement is that it saves traversal and only uses two points. The disadvantage is that the code reuse rate is very low. It can be observed that the codes of the two bisections are very similar. Therefore, we can write it as a function and control the output by passing in a variable. () the following code is from leetcode boss.

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res = new int[] {-1, -1};
        res[0] = binarySearch(nums, target, true);
        res[1] = binarySearch(nums, target, false);
        return res;
    }
    //leftOrRight is true to find the left boundary, false to find the right boundary
    public int binarySearch(int[] nums, int target, boolean leftOrRight) {
        int res = -1;
        int left = 0, right = nums.length - 1, mid;
        while(left <= right) {
            mid = left + (right - left) / 2;
            if(target < nums[mid]) //Indicates that the target is in the interval to the left of the mid at this time
                right = mid - 1;
            else if(target > nums[mid]) //This indicates that the target is in the interval on the right of mid
                left = mid + 1;
            else {
                res = mid; //In this case, res=target, res is already a subscript position.
                //Processing target == nums[mid]
                if(leftOrRight) //If the minimum value is selected, search again in the left section of res at this time.
                    right = mid - 1;
                else
                    left = mid + 1; //If the maximum value is selected, search again in the right section of res at this time.
            }
        }
        return res;
    }
}

69. Square root of X - LeetCode (LeetCode CN. Com)

This problem can also be solved by using the dichotomy algorithm.

class Solution {
    public int mySqrt(int x) {
        if(x == 0 || x == 1)
            return x;
        int left = 1 ,right = x;
        int mid = 1;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if ( mid  > x / mid) {
                right = mid - 1;
            }
            else if (mid  < x / mid) {
                left = mid + 1;
            }
            else {
                return mid;
            }
        }
        return right;
        /* Here is the judgment of the final return value. But in fact, just return right directly
       if (mid > x / mid) {
           return mid - 1; // right
       }
       else
           return mid; //right
       */
        
    }
}

367. Effective complete square force deduction (LeetCode) (LeetCode CN. Com)

For this problem, the easiest solution is given first.

class Solution {
    public boolean isPerfectSquare(int num) {
        if (num == 1)
        return true;
        int left = 1, right = num - 1;
        int mid = 1;
        while ( left <= right) {
            mid = left + (right - left) / 2;
            if (mid > num / mid) {
                right = mid - 1;
            }
            else if (mid < num / mid) {
                left = mid + 1;
            }
            else
                break;
        }
        if ((long)mid * mid == num)
        return true;
        return false;
    }
}

The reason for adding long in the final judgment here is that since integer multiplication will take the remainder directly, if mid == num / mid is directly used, misjudgment will occur. For example, if 2 = = 5 / 2, the judgment result is true. This problem can be judged and processed after obtaining the mid.

Of course, there is a simpler judgment method.

class Solution {
    public boolean isPerfectSquare(int num) {
        if (num == 1)
        return true;
        int left = 1, right = num - 1;
        int mid = 1;
        while ( left <= right) {
            mid = left + (right - left) / 2;
            if (mid > num / mid) {
                right = mid - 1;
            }
            else if (mid < num / mid) {
                left = mid + 1;
            }
            else{
                if (num % mid == 0) //Determine whether to divide by%
                    return true;
                    break; // If this break is not added, the program may fall into an endless loop
            }
                
        }
    
        return false;
    }
}

Posted by djjamiegee on Sun, 12 Sep 2021 14:38:24 -0700