【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)

简介: 【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)

目录

1. 题目解析

2. 算法原理

3. 代码编写

写在最后:


1. 题目解析

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

这道题就是找出目标值在数组中的起始位置和结束位置。

2. 算法原理

这里如果我们直接使用标准的二分去做,如果整个数组都是是同一个数,

就会退化成 O(N),所以这里我们需要对他进行一个优化,

1. 先从查找左端点开始分析:设 x 为 mid 值,t 为目标值

如果 x < t ,left = mid + 1

如果 x >= t ,right = mid(我们这里把大于和等于的情况合并了)

这样设置就在 left == right 的时候就是最终结果,

而我们求中点的方式必须是 left + ( right - left ) / 2(也就是求偶数的形式)

这样每步走会靠近左端点,就不会陷入死循环。

2. 我们再来分析查找右端点

如果 x <= t ,left = mid(为什么这里不用 + 1,因为如果刚好落在目标值上,不久越过了吗)

如果 x > t ,right = mid - 1

这样当 left == right 的时候也就是最终结果了,

而我们求中点的方式就得是 left + ( right - left + 1 ) / 2

这样每步走会靠近右端点,就不会陷入死循环。

3. 代码编写

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.size() == 0) return {-1, -1}; // 处理越界
        int left = 0, right = nums.size() - 1, begin = 0;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) left = mid + 1;
            else right = mid;
        }
        if(nums[left] != target) return {-1, -1};
        else begin = left;
        left = 0, right = nums.size() - 1;
        while(left < right) {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] <= target) left = mid;
            else right = mid - 1;
        }
        return {begin, right};
    }
};

4. 二分的模板

查找左端点的时候:

       while(left < right) {

           int mid = left + (right - left) / 2;

           if(...) left = mid + 1;

           else right = mid;

       }

while (left < right) {
  int mid = left + (right - left) / 2;
  if (...) left = mid + 1;
  else right = mid;
}

查找右端点的时候:

       while(left < right) {

           int mid = left + (right - left + 1) / 2;

           if(...) left = mid;

           else right = mid - 1;

       }

while (left < right) {
  int mid = left + (right - left + 1) / 2;
  if (...) left = mid;
  else right = mid - 1;
}

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果感到有所收获的话可以给博主点一个哦。

如果文章内容有遗漏或者错误的地方欢迎私信博主或者在评论区指出~

相关文章
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
46 3
|
21天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
65 8
|
21天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
59 7
|
2月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
33 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
2月前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
35 4
|
2月前
|
算法 C# 索引
C#二分查找算法
C#二分查找算法
|
2月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
26 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
2月前
|
存储 算法 C语言
【C语言】二分查找算法
【C语言】二分查找算法
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
32 0
|
2月前
|
消息中间件 存储 算法
一文搞懂二分查找算法!
一文搞懂二分查找算法!