LeetCode34 Search for a Range

问题描述:
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found 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]
题源:here;完整实现:here
思路:
两种方案:1 一次二分法;2 两次二分法。
方案1
我们使用一次二分法找到目标值;然后从目标值的坐标往两边扩散,直到遇到非目标值,代码如下:

    vector<int> searchRange_1(vector<int>& nums, int target) {
        int left = 0, right = nums.size()-1;
        while (left <= right){
            int idx = (left + right) / 2;
            if (nums[idx] == target){
                int left_idx = idx, right_idx = idx;
                while (left_idx >=0 && nums[left_idx] == target) left_idx--;
                while (right_idx <= right && nums[right_idx] == target) right_idx++;
                return{ left_idx + 1, right_idx - 1 };
            }
            if (nums[idx] > target){
                right = idx - 1;
            }
            else left = idx + 1;
        }

        return{ -1, -1 };
    }

方案2
两次二分法:第一次找到目标值的左边界;第二次找到目标值的右边界。两次二分法的差别在于判断条件及转移条件,代码如下:

    vector<int> searchRange_2(vector<int>& nums, int target){
        int left = 0, right = nums.size() - 1;
        int rLeft = -1, rRight = -1;

        while (left <= right){
            int mid = (left + right) / 2;
            if (left == right){
                if (nums[mid] == target) rLeft = mid;
                break;
            }
            if (nums[mid] < target) left = mid + 1;
            else right = mid;
        }

        left = 0, right = nums.size() - 1;
        while (left <= right){
            int mid = (left + right+1) / 2;
            if (left == right){
                if(nums[mid] == target) rRight = mid;
                break;
            }
            if (nums[mid] > target) right = mid - 1;
            else left = mid;
        }

        return{ rLeft, rRight };
    }

关于两种方案的思考:
第一种方案初看挺机智的,只用了一次二分法。但是考虑一下特殊情况:
nums: 1,3,3,6,6,6,6,…,6,8,9
target: 6
当中间有非常多的6时,其实算法的复杂度就会趋近于O(n)

猜你喜欢

转载自blog.csdn.net/m0_37518259/article/details/80766018