LC34. 在排序数组中查找元素的第一个和最后一个位置(JAVA)

二分查找

  • 在排序数组中查找元素的第一个和最后一个位置
    • 二分查找
  • 上期经典算法

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

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

给你一个按照非递减顺序排列的整数数组 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 <= 1e5
-1e9 <= nums[i] <= 1e9
nums 是一个非递减数组
-1e9 <= target <= 1e9

LC34. 在排序数组中查找元素的第一个和最后一个位置(JAVA)_第1张图片

二分查找

二分查找(Binary Search)是一种在有序数组中查找特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是目标值,则搜索结束;如果目标值大于或小于中间元素,则在数组大于或小于中间元素的那一半中查找,而不是整个数组。以下是这个算法的步骤:
1.将数组按升序或降序排列。
2.找到数组的中间元素。
3.如果中间元素正好是目标值,则结束搜索。
4.如果目标值小于中间元素,那么只需要在数组的左半部分进行搜索。
5.如果目标值大于中间元素,那么只需要在数组的右半部分进行搜索。
6.重复以上步骤,直到找到目标值,或者搜索区域为空。

二分查找的时间复杂度是O(log n),其中n是数组的元素数量,这使得它在大型数据集合中非常高效。然而,它需要数据是预排序的。

在本题中需要对二分查找坐下小小的修改,第三步时,查到目标值结束搜索,因为要查找左右边界,在这一步就不能停,要继续搜索,下面代码演示。

代码演示:

  /**
     * 找出左右边界
     * @param nums
     * @param target
     * @return
     */
    public int[] searchRange(int[] nums, int target) {
        //临界条件的判断
        if(nums.length == 0 || target < nums[0] || target > nums[nums.length - 1]){
            return new int[]{-1,-1};
        }
        //查找左边界
        int left = leftBound(nums,target);
        //左边界== -1 时,说明没有target 这个值,也就不用找右边界了。
        if(left != -1){
            int right = rightBound(nums,target);
            return new int[]{left,right};
        }
        return new int[]{-1,-1};
    }

    /**
     * 查找左边界
     * @param nums
     * @param target
     * @return
     */
    public int leftBound(int[]nums,int target){
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            //找到值时,不要直接返回,继续向左搜索
            if(nums[mid] == target){
                right = mid - 1;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else if(nums[mid] > target){
                right = mid - 1;
            }
        }
        if(left >= nums.length){
            return -1;
        }
        return nums[left] == target ? left : -1;
    }

    /**
     * 查找右边界
     * @param nums
     * @param target
     * @return
     */
    public int rightBound(int[]nums,int target){
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            //找到目标值,不要立马返回,向右继续搜索。
            if(nums[mid] == target){
                left = mid + 1;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else if(nums[mid] > target){
                right = mid - 1;
            }
        }
        if(right < 0 ){
            return -1;
        }
        return nums[right] == target ? right : -1;
    }

上期经典算法

leetcode3. 无重复字符的最长子串

你可能感兴趣的:(算法,数据结构,java,java,python,算法,leetcode,数据结构,贪心算法,动态规划)