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


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

    题目

    难度中等739

    给定一个按照升序排列的整数数组 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

    左闭右开写法一(推荐):

    第一次:二分搜索,找到一个大于等于target的值。

    第二次:二分搜索,找到一个大于target的值。

    class Solution {
        public int[] searchRange(int[] nums, int target) {
            int[] ans = new int[]{-1,-1};
            if(nums == null)
                return ans;
            // 第一次:二分搜索,找到一个大于等于target的值。
            // 定义一个区间:[left,right), 左侧小于target,右侧大于等于target
            int left = 0, right = nums.length;
            while(left < right) {
                int mid = left + (right - left)/2;
                if(nums[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid;
                }
            }
            // 判断是否越界
            if(left >= nums.length || nums[left] != target) {
                return ans;
            }
    		ans[0] = left;
            // 第二次:二分搜索,找到一个大于target的值。
            // 定义一个区间[left,right) 左侧小于等于target, 右侧大于target
            right = nums.length;
            while(left < right) {
                int mid = left + (right - left)/2;
                if(nums[mid] <= target) {
                    left = mid + 1;
                } else {
                    right = mid;
                }
            }
            ans[1] = left -1;
          return ans;
        }
    }
    

    写法二:半闭半开区间写法(反向写法)

    我们设定一个区级: 区间左侧小于target, 右侧大于等于target ====>[a,b)

    通过这种方法我们可以定位左侧第一个元素;

    class Solution {
        public int[] searchRange(int[] nums, int target) {
            int[] ans = new int[]{-1,-1};
            if(nums == null)
                return ans;
            int left = 0, right = nums.length;
            while(left < right) {
                int mid = left + (right - left)/2;
                if(nums[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid;
                }
            }
            // 判断是否存在target
            if(left >= nums.length || nums[left] != target) {
                return ans;
            }
    
            ans[0] = left;
            //System.out.println(Arrays.toString(ans));
            left = left - 1;
            right = nums.length - 1;
            while(left < right) {
                // 过程相反
                int mid = right - (right - left)/2;
                if(nums[mid] <= target) {
                    left = mid;
                } else {
                    right = mid - 1;
                }
            }
            ans[1] = left;
            return ans;
     
        }
    }
    

    闭区间写法(我觉得容易错)

    class Solution {
        public int[] searchRange(int[] nums, int target) {
            int[] ans = new int[]{-1,-1};
            if(nums == null)
                return ans;
            int left = 0, right = nums.length -1;
            while(left < right) {
                int mid = left + (right - left)/2;
                if(nums[mid] >= target) {
                    right = mid;
                } else {
                    left = mid + 1;
                }
            }
            // 判断是否存在target
            if(ans[left] != target ){
                return ans;
            }
             ans[0] = left;
            right = nums.length -1;
            while(left < right) {
                // 过程相反
                int mid = left + (right - left)/2;
                // 区间左侧的值,小于等于target
                if(nums[mid] <= target) {
                    left = mid;
                } else {
                    right = mid -1;
                }
            }
            ans[1] = left;
            return ans;
     
        }
    }
    
  • 相关阅读:
    如何编写自己的Linux安全检查脚本?
    ubuntu桌面版打开终端Terminal的几种方法
    Docker 学习笔记(CentOS 7.1)
    发送验证码倒计时
    在Thinkphp中使用AJAX实现无刷新分页
    php加密解密
    浏览器用户用滤镜实现网页的翻转效果
    PHP定时执行任务的实现
    PHP GBK UTF8互转
    在php4下可用,简单的php数组转成json格式,
  • 原文地址:https://www.cnblogs.com/sidewinder/p/14072122.html
Copyright © 2020-2023  润新知