【LeetCode】34. 在排序数组中查找元素的第一个和最后一个位置
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题基础上,做些修改。依次找到左右边界。
- 寻找左边界:有两种情况
- 如果整个数组中没有target的值,那最后返回的就是第一个比target大的元素位置的索引;
- 如果找到了target的值,不能停,左边界可能还有值,需要将搜索区间移动到mid左边,即right=mid-1;这时候会出现两种情况:
- 1.在左区间又找到了target。
- 2.在左区间没有target了。
要清楚的是最后一次执行的一定是left=right=mid,而且mid左侧都小于target,mid右侧的值都大于等于target,如果判断mid这时候的值也小于target,那left=mid+1,正好就是第一个等于target的值。
- 寻找右边界:有两种情况
- 如果整个数组中没有target的值,那最后返回的就是第一个比target小的位置的索引;
- 如果找到了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. 在排序数组中查找元素的第一个和最后一个位置的更多相关文章
- Java实现 LeetCode 34 在排序数组中查找元素的第一个和最后一个位置
在排序数组中查找元素的第一个和最后一个位置 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n ...
- LeetCode 34 - 在排序数组中查找元素的第一个和最后一个位置 - [二分][lower_bound和upper_bound]
给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...
- leetcode 34在排序数组中查找元素的第一个和最后一个位置
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { ve ...
- Leetcode题目34.在排序数组中查找元素的第一个和最后一个位置(中等)
题目描述: 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标 ...
- 【LeetCode】34-在排序数组中查找元素的第一个和最后一个位置
题目描述 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值 ...
- 【LeetCode】在排序数组中查找元素的第一个和最后一个位置【三次二分】
给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...
- 34、在排序数组中查找元素的第一个和最后一个位置 | 算法(leetode,附思维导图 + 全部解法)300题
零 标题:算法(leetode,附思维导图 + 全部解法)300题之(34)在排序数组中查找元素的第一个和最后一个位置 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: / ...
- Leetcode题库——34.在排序数组中国查找元素的第一个和最后一个位置
@author: ZZQ @software: PyCharm @file: searchRange.py @time: 2018/11/12 19:19 要求:给定一个按照升序排列的整数数组 num ...
- #leetcode刷题之路34-在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置.你的算法时间复杂度必须是 O(log n) 级别.如果数组中不存在目标值,返回 [-1 ...
随机推荐
- hdu5438 拓扑排序+DFS
解析 对一个有向无环图(Directed Acyclic Graph,简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则 ...
- JUnit5注解学习指引
注解(Annotations)是JUnit的标志性技术,本文就来对它的20个注解,以及元注解和组合注解进行学习. 20个注解 在org.junit.jupiter.api包中定义了这些注解,它们分别是 ...
- Unity 异步加载 进度条
当我们进行游戏开发时,时常会进行场景切换,如果下个场景较大,切换时就会出现卡顿现象,甚至看起来像是"死机",非常影响用户体验,我们这时就可以运用异步加载,在界面上显示加载的进度条以 ...
- Redis配置统计字典
本章将对Redis的系统状态信息(info命令结果)和Redis的所有配置(包括Standalone.Sentinel.Cluster三种模式)做一个全面的梳理,希望本章能够成为Redis配置统计字典 ...
- Custom Controller CollectionQT样式自定义 002 :NoteSlider 标签滑动条
先上效果图 这个效果可以根据需求再定制,比如说文本框换成一个点下出现的气泡,跟随游标移动. 思路:继承QSlider,重写鼠标事件,添加label部件,定义其动作事件 源码:https://githu ...
- 再看Lambda架构
博客原文地址 最*看了一本<大数据系统构建>的书,发现之前对于Lambda架构的理解还是不够深入和清晰. 之前对Lambda架构的理解 Azure文档上有一张Lambda架构的图, 同时也 ...
- Python实现 利用朴素贝叶斯模型(NBC)进行问句意图分类
目录 朴素贝叶斯分类(NBC) 程序简介 分类流程 字典(dict)构造:用于jieba分词和槽值替换 数据集构建 代码分析 另外:点击右下角魔法阵上的[显示目录],可以导航~~ 朴素贝叶斯分类(NB ...
- java基础---类和对象(2)
一.继承(extends) 面向对象的三大特性之一,当多个类中存在相同属性和行为时,将这些内容抽取到一个公共类中,让多个类(子类)吸收公共类(父类.超类)中已有特征和行为,而在多个类型只需要编写自己独 ...
- python 元组推导式
>>> b=(page for page in range(10))>>> print(b)<generator object <genexpr> ...
- vscode搭建python环境
这两天刚下了一个pycharm,结果使用之后将vscode给崩了,重装的时候有些步骤也记不清,走了一些弯路,做个总结来记录一下(本人觉得vscode比pycharm好用一点). Python下载安装 ...