• 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;
     
        }
    }
    
  • 相关阅读:
    codeforces 587B
    codeforces 552E
    算法竞赛模板 字典树
    算法竞赛模板 二叉树
    算法竞赛模板 图形面积计算
    TZOJ 1545 Hurdles of 110m(动态规划)
    算法竞赛模板 判断线段相交
    算法竞赛模板 折线分割平面
    TZOJ 3005 Triangle(判断点是否在三角形内+卡精度)
    算法竞赛模板 KMP
  • 原文地址:https://www.cnblogs.com/sidewinder/p/14072122.html
Copyright © 2020-2023  润新知