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

知识点:数组,二分查找

题目描述

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4] 输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1] 输入:nums = [], target = 0
输出:[-1,-1]

解法一:二分查找

这是一道典型的二分查找的问题,只不过这次需要我们返回左右边界。

在基础的二分法也就是35题基础上,做些修改。依次找到左右边界。

  • 寻找左边界:有两种情况
  1. 如果整个数组中没有target的值,那最后返回的就是第一个比target大的元素位置的索引;
  2. 如果找到了target的值,不能停,左边界可能还有值,需要将搜索区间移动到mid左边,即right=mid-1;这时候会出现两种情况:
    • 1.在左区间又找到了target。
    • 2.在左区间没有target了。

      要清楚的是最后一次执行的一定是left=right=mid,而且mid左侧都小于target,mid右侧的值都大于等于target,如果判断mid这时候的值也小于target,那left=mid+1,正好就是第一个等于target的值。
  • 寻找右边界:有两种情况
  1. 如果整个数组中没有target的值,那最后返回的就是第一个比target小的位置的索引;
  2. 如果找到了target的值,不能停,右边界可能还有值,需要将搜索区间移动到mid右边,即leftt=mid+1;这时候会出现两种情况:
    • 1.在右区间又找到了target。
    • 2.在右区间没有target了。

      要清楚的是最后一次执行的一定是left=right=mid,而且mid左侧都小于等于target,mid右侧的值都大于target,如果判断mid这时候的值大于target,那right=mid-1,正好就是第一个等于target的值。

总的来说(关键)

  • 左边界其实就是在找第一个>=target的位置

    • 如果数组中有target,返回就是第一个target的位置;
    • 如果数组中无target,返回就是第一个比target大的元素是位置(或者可以理解成要插入target的位置);
  • 右边界其实就是在找最后一个<=target的位置
    • 如果数组中有target,返回就是最后target的位置;
    • 如果数组中无target,返回就是最后一个小于target的位置(或者可以理解成要插入的target的位置的前一个位置)。

所以最后就可以直接比较left和right的位置了,如果left比right还大,那证明不存在了。

class Solution {
public int[] searchRange(int[] nums, int target) {
int left = leftBound(nums, target);
int right = rightBound(nums, target);
while(left > right) return new int[]{-1, -1};
return new int[] {left, right};
}
private int leftBound(int[] nums, int target){
int left = 0, right = nums.length-1;
while(left <= right){
int mid = left + ((right-left) >> 1);
if(target <= nums[mid]){ //将等于合并过来;
right = mid-1;
}else{
left = mid+1;
}
}
return left; //第一个比大于等于target的索引;
}
private int rightBound(int[] nums, int target){
int left = 0, right = nums.length-1;
while(left <= right){
int mid = left + ((right-left) >> 1);
if(target >= nums[mid]){
left = mid+1;
}else{
right = mid-1;
}
}
return right;
}
}

体会

注意去思考里面的细节,思考左右边界是如何获取到的。要抓住最关键的:最后一次执行的一定是left=mid=right,三个是同一个数,而且mid左侧都比目标值小,mid右侧都比目标值大,这时候就看mid值,如果比t大,那执行right=mid-1;返回left就是正好当前值,当前值比t大,当然也可能包括t;如果比t小,那执行left=mid+1;返回的left移动一位就比t大了。

【LeetCode】34. 在排序数组中查找元素的第一个和最后一个位置的更多相关文章

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

    在排序数组中查找元素的第一个和最后一个位置 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n ...

  2. LeetCode 34 - 在排序数组中查找元素的第一个和最后一个位置 - [二分][lower_bound和upper_bound]

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...

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

    class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { ve ...

  4. Leetcode题目34.在排序数组中查找元素的第一个和最后一个位置(中等)

    题目描述: 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标 ...

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

    题目描述 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值 ...

  6. 【LeetCode】在排序数组中查找元素的第一个和最后一个位置【三次二分】

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...

  7. 34、在排序数组中查找元素的第一个和最后一个位置 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(34)在排序数组中查找元素的第一个和最后一个位置 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: / ...

  8. Leetcode题库——34.在排序数组中国查找元素的第一个和最后一个位置

    @author: ZZQ @software: PyCharm @file: searchRange.py @time: 2018/11/12 19:19 要求:给定一个按照升序排列的整数数组 num ...

  9. #leetcode刷题之路34-在排序数组中查找元素的第一个和最后一个位置

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置.你的算法时间复杂度必须是 O(log n) 级别.如果数组中不存在目标值,返回 [-1 ...

随机推荐

  1. 深入理解 sync.Once 与 sync.Pool

    深入理解 sync.Once 与 sync.Pool sync.Once 代表在这个对象下在这个示例下多次执行能保证只会执行一次操作. var once sync.Once for i:=0; i & ...

  2. Golang超时机制--2秒内某个函数没被调用就认为超时

    Golang超时机制--2秒内某个函数没被调用就认为超时 需求描述 当一整套流程需要其他程序来调用函数完成时通常需要一个超时机制,防止别人程序故障不调你函数导致你的程序流程卡死 实现demo pack ...

  3. Java基准性能测试--JMH使用介绍

    JMH是什么 JMH是Java Microbenchmark Harness的简称,一个针对Java做基准测试的工具,是由开发JVM的那群人开发的.想准确的对一段代码做基准性能测试并不容易,因为JVM ...

  4. (Element UI 组件 Table)去除单元格底部的横线

    Element UI 组件 Table 有一个属性 border,添加它可以增加纵向边框,但是无法控制横线边框,因此即使是最简单的 el-table,也会包含一个底部横线. 这个底部横线其实是一个 b ...

  5. 在Excel中当遇到多个对象的目标值都不同时,如何快速设置条件格式突出未达标的对象

    1.选择实际值的一个单元格,选择条件格式,新建规则,选择图中选项. 2.这里选择大于,然后选择对比的单元格.选择需要的格式确定.(因为要对比的目标值不同,所以需要给单元格去掉绝对引用,也就是$符号). ...

  6. 16、mysql主从复制问题总结

    16.1.主库"show master status"没有结果: 1.原因: 主库binlog功能开关没有改或没有生效: 2.解决办法: (1)[root@backup ~]#eg ...

  7. frp+nginx内网穿透

    frp+nginx内网穿透 背景:自己有台内网Linux主机,希望被外网访问(ssh.http.https): 准备工作 内网Linux主机-c,可以访问c主机和外网的主机-s(windows/lin ...

  8. Spring中这么重要的AnnotationAwareAspectJAutoProxyCreator类是干嘛的?

    大家好,我是冰河~~ 停更了很久的[Spring注解系列]专题,终于重新更新了,我们还是接着之前的文章继续往下更新.在<[Spring注解驱动开发]二狗子让我给他讲讲@EnableAspectJ ...

  9. 如何使用Linux lsblk命令列出块设备信息

    译至:http://linoxide.com/linux-command/linux-lsblk-command/ lsblk命令(列出块设备)用于列出所有可用的块设备的信息,但是, 它并没有列出有关 ...

  10. linux学习之路第五天(文件目录类第一部分)

    文件目录类 pwd 指令 基本语法 pwd (显示当前目录的绝对路径) Ls 指令 cd 指令 -代表的是上一级目录 mkdir指令 用于创建目录 基本语法 mkdir [选项] 要创建的目录 常用选 ...