LeetCode-034-在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-1, -1]。

示例 1:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array

解题思路

二分查找, 定义两个指针, int i = 0, j = len - 1

  1. 先找出第一个位置
    1. 找出中间数nums[mid = (i + j) >> 1]
    2. 如果中间数>=目标, 则左边界在mid及其左边, 更新索引j = mid
    3. 反之左边界在mid及其右边i = mid + 1
  2. 当两个索引重叠时跳出循环, 如果索引越界或者索引所指的数不等于目标数, 则说明没有找到目标, 则直接返回{-1, -1}
  3. 否则将result[0] = i记录第一个位置
  4. 然后找出第二个位置, 这里要改变为"找出第二个位置的下一个位置"

    因为用类似找第一个位置的方法来找第二个位置, 会陷入死循环, 索性按照找左边界的思想, 只不过这次找的是比目标数大的那部分的左边界
    1. 这次定义i = 0, j = len, 这里j将来指向右边界
    2. 还是找出中间数
    3. 如果中间数大于目标数, 则右边界在mid及其左边, 更新索引j = mid
    4. 反之右边界在mid右边, 更新索引i = mid + 1
    5. 记录右边界result[1] = j - 1

代码

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] result = {-1, -1};
        int i = 0, j = nums.length - 1;
        // 先找出target的左边界
        while (i < j) {
            int mid = (i + j) >> 1;
            // 如果中间数>=目标, 则左边界在mid及其左边
            if (nums[mid] >= target) {
                j = mid;
            } else { // 反之在mid右边
                i = mid + 1;
            }
        }
        // 如果索引越界或者索引所指数不等于目标, 则说明没有找到目标
        if (i >= nums.length || nums[i] != target) {
            return result;
        }
        result[0] = i;
        i = 0;
        j = nums.length;
        // 接着找出target的右边界
        while (i < j) {
            int mid = (i + j) >> 1;
            if (nums[mid] > target) {
                j = mid;
            } else {
                i = mid + 1;
            }
        }
        result[1] = j - 1;
        return result;
    }
}

你可能感兴趣的:(LeetCode-034-在排序数组中查找元素的第一个和最后一个位置)