力扣刷题 - 34. 在排序数组中查找元素的第一个和最后一个位置

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

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

进阶:你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109
首先分析一下题目:
	
	数组是一个升序的数组,没有说数组中的元素是单一的,那么他的返回值的情况有:
	1、当 target 在数组中找到了,如果 target 在数组中不止 1 个,那么返回的是 【i,j】;
	2、当 target 在数组中只有一个,返回的是 【i,i】;
	3、没有找到返回 【-1-1.
	
	常规想法:
		直接遍历数组找到 target 出现的第一个位置,记为 i, 继续遍历数组,找下一个出现的位置,记为 j , 
		当然 j 可能会变化,因为可能下一个位置还是 target,当遍历到不是 target 结束循环,i j 的位置就是我们的结果,
		之后就是分情况讨论了。【如下面代码的第一种解法】

	从运行情况看,这显然不是最好的做法,那么该怎么做呢?二分法
		利用二分思想先找其左边界,再找其右边界即可,注意找左边界的时候,由右侧逼近;
		找右边界的时候,由左侧逼近,即可。【如下面代码的第二种解法】
  • 第一种解法:
class Solution {

    public static int[] searchRange(int[] nums, int target) {
        int start = -1, end = -1;
        boolean first = false; // 记录是否是第一次定位到 target
        int len = nums.length;
        for(int i=0;i<len;i++){
            if(!first){
                if(target == nums[i]){
                    start = i;
                    first = true;
                }
            } else {
                if(target == nums[i]){
                    end = i;
                }
            }
        }

        int[] res = new int[] {-1, -1};
        if(first){  // 找到了 target
            res[0] = start;
            if(end == -1){ // target 出现的次数不止一次
                res[1] = start;
            } else {
                res[1] = end;
            }
            return res;
        } 
        // 没有找到 target
        return res;
    }
}

力扣刷题 - 34. 在排序数组中查找元素的第一个和最后一个位置_第1张图片

  • 第二种解法:
class Solution {
   public static int[] searchRange(int[] nums, int target) {
        int[] res = new int[] {-1, -1};
        res[0] = findRange(nums, target, true);   //找左边界
        res[1] = findRange(nums, target, false);  //找右边界
        return res;
    }

    public static int findRange(int[] nums,int target,boolean left_right){
        int res = -1;
        int left = 0, right = nums.length - 1, mid;
        while(left <= right) {    //二分查找
            mid = (left + right)>>1;
            if(target < nums[mid]) {
                right = mid - 1;
            } else if(target > nums[mid]) {
                left = mid + 1;
            } else {
                res = mid;
                if(left_right) { //往左边找
                    right = mid - 1;
                } else {    //往右边找  
                    left = mid + 1;
                }
            }
        }
        return res;
    }
}

力扣刷题 - 34. 在排序数组中查找元素的第一个和最后一个位置_第2张图片

你可能感兴趣的:(算法学习,leetcode,算法,职场和发展,java,数据结构)