【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 ...
随机推荐
- 『心善渊』Selenium3.0基础 — 13、Selenium操作下拉菜单
目录 1.使用Selenium中的Select类来处理下拉菜单(推荐) 2.下拉菜单对象的其他操作(了解) 3.通过元素二次定位方式操作下拉菜单(重点) (1)了解元素二次定位 (2)示例: 页面中的 ...
- 11 监控MySQL主从状态是否异常
#!/bin/bash source /etc/profile # 主从同步 # master:binlog # slave:relaylog # 写->master->binlog< ...
- Redis 底层数据结构之字典
文章参考 <Redis 设计与实现>黄建宏 字典 在字典中,每个键都是独一无二的,程序可以在字典中根据键查找与之相关联的值,或者通过键来更新和删除值. 字典在 Redis 中的应用相当广泛 ...
- 小程序开发 access_token 统一管理
TOKEN 定时刷新器 一.背景 对于使用过公众平台的API功能的开发者来说,access_token绝对不会陌生,它就像一个打开家门的钥匙,只要拿着它,就能使用公众平台绝大部分的API功能.因此,对 ...
- webpack(9)plugin插件功能的使用
plugin 插件是 webpack 的支柱功能.webpack 自身也是构建于你在 webpack 配置中用到的相同的插件系统之上! 插件目的在于解决 loader 无法实现的其他事. 常用的插件 ...
- Python—IP地址与整数之间的转换
1. 将整数转换成IP: 思路:将整数转换成无符号32位的二进制,再8位进行分割,每8位转换成十进制即可. 方法一:#!usr/bin/python 2 #encoding=utf-8 3 #1. 将 ...
- 【保姆级】Python项目(Flask网页)部署到Docker的完整过程
大家好,我是辰哥~ 前提:相信看到这篇文章的读者应该已经学会了Docker的安装以及Docker的基本使用,如果还不会的可以参考我之前的文章进行详细学习! 1.安装版:2300+字!在不同系统上安装D ...
- C语言中函数的返回值
规则 除局部变量的内存地址不能作为函数的返回值外,其他类型的局部变量都能作为函数的返回值. 我总结出下面这些规则: int.char等数据类型的局部变量可以作为函数返回值. 在函数中声明的指针可以作为 ...
- Python图表库Matplotlib 组成部分介绍
图表有很多个组成部分,例如标题.x/y轴名称.大刻度小刻度.线条.数据点.注释说明等等. 我们来看官方给的图,图中标出了各个部分的英文名称 Matplotlib提供了很多api,开发者可根据需求定制图 ...
- Gradle入门第一集【下载,安装和测试】
参考:https://www.cnblogs.com/panchanggui/p/9394760.html 1,http://services.gradle.org/distributions/链接下 ...