[LeetCode] 34. Find the first and last positions of the element in the sorted array (the same sword refers to Offer 53-I)

1. Topic

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].

Advanced:

  • Can you design and implement an O(log n) algorithm to solve this problem?

Example 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

Example 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

Example 3:

输入:nums = [], target = 0
输出:[-1,-1]

prompt:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums is a non-decreasing array
  • -109 <= target <= 109

Two, solve

1. Binary search method

Idea:
Sort numsall the numbers in the array to targetform a window, remember that the left/right boundary indexes of the window are respectively leftand right, respectively corresponding to the first element on the left/right of the window.

The number of targetoccurrences of a number can be transformed into: the dichotomy method finds the left boundary leftand the boundary respectively right, and the number targetof easy-to-obtain numbers is right-left-1.
1

Algorithm analysis:

  1. Initialization : left boundary i = 0, with boundary j = len(nums)-1.
  2. Cycle dichotomy : [i, j]Jump out when there is no element in the closed interval :
    2.1. Calculate the midpoint m = (i+j)/2(rounded down)
    2.2. If nums[m]<target, then the target is in the closed interval [m+1, j], so execute i = m+1;
    2.3. If nums[m]>target, then the target is in the closed interval [i, m-1], so execute j = m-1;
    2.4. If nums[m]=target, then the right boundary is in the interval [m+1, j]; the left boundary is in the closed interval [i, m-1]. Therefore, it is divided into the following two cases:
    [1]. If you find the right boundary right, then execute i = m+1; (when jumping out, i points to the right boundary)
    [2]. If you find the left boundary left, then execute j = m-1; (when jumping out j points to the left boundary)
  3. Return value . Apply the dichotomy twice, find the rightsum respectively left, and return it finally right-left-1.

Code-Version 1:

class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        // 搜索右边界 right
        int i = 0, j = nums.length - 1;
        while(i <= j) {
    
    
            int m = (i + j) / 2;
            if(nums[m] <= target) i = m + 1;
            else j = m - 1;
        }
        int right = i;
        // 若数组中无 target ,则提前返回
        if(j >= 0 && nums[j] != target) return 0;
        // 搜索左边界 right
        i = 0; j = nums.length - 1;
        while(i <= j) {
    
    
            int m = (i + j) / 2;
            if(nums[m] < target) i = m + 1;
            else j = m - 1;
        }
        int left = j;
        return right - left - 1;
    }
}

Time complexity: O (logn) O(logn)O ( l o g n )
space complexity: O (1) O(1)O ( 1 )

The above code is less readable and can be optimized to the following version:

Code-Version 2:

class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        return helper1(nums, target) - helper2(nums, target) - 1;
    }

    public int helper1(int[] nums, int target) {
    
    
        int left = 0, right = nums.length - 1;
        while (left <= right) {
    
    
            int mid = (left + right) / 2;
            if (nums[mid] <= target) left = mid + 1;
            else right = mid - 1;
        }
        return left;
    }

    public int helper2(int[] nums, int target) {
    
    
        int left = 0, right = nums.length - 1;
        while (left <= right) {
    
    
            int mid = (left + right) / 2;
            if (nums[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return right;
    }
}

The above code is quite redundant and can be further optimized:

Code-Version 3:

class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        return helper(nums, target) - helper(nums, target - 1);
    }
    int helper(int[] nums, int tar) {
    
    
        int i = 0, j = nums.length - 1;
        while(i <= j) {
    
    
            int m = (i + j) / 2;
            if(nums[m] <= tar) i = m + 1;
            else j = m - 1;
        }
        return i;
    }
}

Time complexity: O (n) O(n)O ( n )
space complexity: O (n) O(n)O ( n )

Three, reference

1. Interview Question 53-I. Find the number I in a sorted array (Dichotomy, clear illustration)

Guess you like

Origin blog.csdn.net/HeavenDan/article/details/110920731