栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

算法练习-二分法 LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

算法练习-二分法 LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

今日感受: (ง •_•)ง 

题目描述:

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

 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

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

输出:[3,4]

解题代码:

class Solution {



    public static int FindFirstIndex(int[] nums, int target){
        int l = 0, r = nums.length -1;

        while(l < r){
            int midIndex = (l+r)/2;
            // 更新边界
            if(nums[midIndex] >= target){
                r = midIndex;
            }else if(nums[midIndex] < target){
                l = midIndex + 1;
            }
        }
        
        if (nums[r] == target){
            return r;
        }
        return -1;
    }


    public static int FindLastIndex(int[] nums, int target){
        int l = 0, r = nums.length -1;

        while(l < r){
            int midIndex = (l+r+1)/2;
            System.out.println(midIndex);
            // 更新边界
            if(target >= nums[midIndex]){
               l = midIndex; // l = midIndex 需要 midIndex = (l+r+1)/2 (加1的目的向上取正)
            }else{
               r = midIndex-1;
            }
        }
        if (nums[r] == target){
                return r;
        }
        return -1;
    }

    public int[] searchRange(int[] nums, int target) {
        int [] res = new int[2];
        if(nums.length == 0){
            res[0] = -1;
            res[1] = -1;
            return res;
        }
        res[0] = Solution.FindFirstIndex(nums,target);
        res[1] = Solution.FindLastIndex(nums,target);
       
        return res;
    }
}

提交结果:

解题思路:

要求时间复杂度为O(log n),则采用二分法。

(1)采用两个二分法

         FindFirstIndex(int[] nums, int target) : 第一个二分找第一个target的index。

         FindLastIndex(int[] nums, int target) : 第二个二分找倒数第一个target的index。


(2)虽然本质都是使用二分法进行搜索,但是一定要注意边界更新问题以及midIndex取值问题


(3) FindFirstIndex(int[] nums, int target) 方法: 第一个二分找第一个target的index。

           1. 确定边界 l = 0, r = nums.length -1;

           2. 确定循环遍历条件 while(l < r) : l == r 的时候跳出循环(找到唯一点)

           3. midIndex = (l+r)/2

           4. 确定更新边界条件:(往左逼近)

                nums[midIndex] >= target 更新 r = midIndex; 

              【注意:条件是 >= ,保证即使连续几个相同的target值在数组内,确保边界更新向最前移动并最终指向的是第一个】

                 nums[midIndex] < target 更新 l = midIndex + 1; (闭区间取所有可能的值)

        5. 结束循环之后判断当前找到的值是否与target值相同,是则返回 r 边界(即第一个target的Index值),否则返回-1.


(4)  FindLastIndex(int[] nums, int target) 方法:第二个二分找倒数第一个target的index。

           1. 确定边界 l = 0, r = nums.length -1;

           2. 确定循环遍历条件 while(l < r) : l == r 的时候跳出循环(找到唯一点)

           3. 注意此时的 midIndex = (l+r+1)/2 而不是 midIndex = (l+r)/2

               原因:由于除法是向下取整,所以midIndex = (l+r)/2 向下取整,刚好符合向左逼近。然而此时寻找最后一个是向右逼近,所以需要向上取整 midIndex = (l+r+1)/2 (此时加1实现向上取整)。如果不加1的话,无法跳出循环,midIndex 始终为数组倒数第二个Index值(因为不加1,除法就是向下取整,最后一个Index值取不到)。

           4. 确定更新边界条件:(往右逼近)

                nums[midIndex] <= target 更新 l = midIndex;

              【注意:条件是 <= ,保证即使连续几个相同的target值在数组内,确保边界更新向最后移动并最终指向的是最后一个】

                 nums[midIndex] > target 更新 r = midIndex-1; (闭区间取所有可能的值)。

           5. 结束循环之后判断当前找到的值是否与target值相同,是则返回 r 边界(即第一个target的Index值),否则返回-1.


(5)在searchRange方法中

        1. 首先判断nums是否为空 (一定注意)

        2. 通过类名直接调用定义的静态方法FindFirstIndex和FindLastIndex

                 res[0] = Solution.FindFirstIndex(nums,target);

                 res[1] = Solution.FindLastIndex(nums,target);

        然后 return res 。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/974095.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号