力扣-->#34. 在排序数组中查找元素的第一个和最后一个位置-->数组-中等(二分查找)

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.逐个遍历,若第一次与目标值相等,则将此索引赋值给first与last这两个最终返回的结果,这里要记住,也要赋值给last,否则若数组中只有一位数且该数为目标值,那么last只是-1,而非该数的索引;
2.若非第一次与目标值相等(此时last!=-1),则将此索引赋值给last,
3.若该数与目标值不等,且last!=-1,说明该数组中已经曾经与目标值相等过,利用已排序的数组这一特性,直接跳出循环。

执行结果:通过
执行用时:1 ms, 在所有 Java 提交中击败了13.67%的用户
内存消耗:41.5 MB, 在所有 Java 提交中击败了70.44%的用户
通过测试用例:88 / 88

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int first=-1;
        int last=-1;
        // int[] result=new int[]{first,last};//不能在此处先定义,否则result恒为[-1,-1]
        for(int index=0;index<nums.length;index++){
            if(nums[index]==target && first==-1){
                first=index;
                last=index;     //若不加这句,那么在判断是类似[1] 1这类组合的时候,会返回[0,1]
            }else if(nums[index]==target && first!=-1){
                last=index;
            }else if(nums[index]!=target && last!=-1){
                break;
            }
        }
        return new int[]{first,last};
    }
}

方法二:二分查找法
思路:
1.二分查找法直接利用题给数组已经排好序的特点,设置了两个结点left与right,分别用于记录最终返回等于目标数的数组左右索引,设计了一个二分查找的方法binarySearch,这个方法用于找到第一个大于目标值的数的索引;
2.对于left,在binarySearch方法中找到第一个大于target-1的数的索引,这个索引就是第一个等于target的数的索引;
3.对于right,在binarySearch方法中找到第一个大于target的数的索引,这个索引 -1 就是最后一个等于target的数的索引;
4.最后判断,若nums[left]==target,说明在数组中能找到一个与target相等的值,返回最终索引;而left<=right这个判断用于表示所传数组非空,若数组为[ ],则会报出索引溢出的异常。

执行结果:通过
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:41.6 MB, 在所有 Java 提交中击败了44.37%的用户
通过测试用例:88 / 88

class Solution {
    public int[] searchRange(int[] nums, int target) {
        //left-->第一个比target-1大的元素的索引,正好就是target的第一个索引
        int left=binarySearch(nums,target-1);   
        //right-->binarySearch(nums, target)返回的是第一个比target大的元素,减1是返回等于target的最后一个元素
        int right=binarySearch(nums,target)-1;
        if(left<=right && nums[left]==target){  //若无left<=righ,则容易发生left溢出
            return new int[]{left,right};
        }
        return new int[]{-1,-1};
    }

    //寻找第一个大于target的数的下标
     private int binarySearch(int[] nums,int target){//二分查找
        int left=0, right=nums.length-1, index=nums.length;
        while(left<=right){
            int mid=(left+right)/2;
            if(nums[mid]>target){//如果最中间的值>目标值
                right=mid-1;    //将右指针移到中间值左边(此时num[mid]可能==target)
                index=mid;      //记录第一个大于target的数的索引
            }else{
                left=mid+1;
            }
        }
        return index;
    }

}

平平无奇小白程序媛一枚,欢迎各位大佬交流指教,如有不正确的地方,欢迎留言改正,谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值