当前位置: 首页 > news >正文

每日一题:二分查找

文章目录

  • 一、思路一:常规思路
    • 1、寻找固定值
    • 2、寻找左边界
    • 3、寻找右边界
  • 二、思路二:红蓝法二分
  • 三、模板题
    • 1、二分查找
    • 2、在排序数组中查找元素的第一个和最后一个位置

二分查找,顾名思义,就是每次筛选能晒掉一半的数据。 二分查找主要用在数据有单调特性或者有二段性

二分查找,虽然是基础算法,但是需要注意的细节非常的多,这里主要提供两种二分查找的思路,可以根据自己的理解程度去进行选择。

一、思路一:常规思路

二分查找需要注意的就是两点:一是循环条件,二是求中点的方法。

// 循环条件
left < right;
left <= right;// 求中点的方法
(left + right) / 2; // 可能有数据溢出的风险
left + (right - left) / 2;
left + (right - left + 1) / 2;

1、寻找固定值

image-20241002234338271

/**************************  
写法一:
循环条件:left <= right
寻找中间值:上述的寻找中间值方法都行
left 和 right 的初始值是 0 和 nums.size() - 1
**************************/
int BinarySearch(vector<int> nums, int target)
{sort(nums.begin(), nums.end());int left = 0, right = nums.size() - 1; // 注意while (left <= right) // 注意{int mid = (left + right) / 2;if (nums[mid] < target)left = mid + 1;else if (nums[mid] > target)right = mid - 1;elsereturn nums[mid] == target ? mid : -1;}return -1;
}

image-20241003010056062

/**************************  
写法二:
循环条件:left < right
寻找中间值:上述的寻找中间值方法都行
left 和 right 的初始值是 0 和 nums.size()
**************************/
int BinarySearch(vector<int> nums, int target)
{sort(nums.begin(), nums.end());int left = 0, right = nums.size();while (left < right){int mid = (left + right) / 2;if (nums[mid] < target)left = mid + 1;else if (nums[mid] > target)right = mid;elsereturn nums[mid] == target ? mid : -1;}return -1;
}

2、寻找左边界

循环条件:left < right(不能有等于,这样会导致死循环)

求中点的方法:left + (right - left) / 2(这个和另外一个防止溢出的方法,唯一不同的是当数组元素个数是偶数的时候中间值是左边还是右边的问题)

image-20241003011553793

int FindLeft(vector<int>& nums, int target){int l = 0, r = nums.size() - 1;while (l < r){int mid = l + (r - l) / 2;if (nums[mid] < target) l = mid + 1;else r = mid;}if (nums[l] != target) return -1;return l;}

3、寻找右边界

循环条件:left < right(不能有等于,这样会导致死循环)

求中点的方法:left + (right - left + 1) / 2

image-20241003012426728

int FindRight(vector<int>& nums, int target){int l = 0, r = nums.size() - 1;while (l < r){int mid = l + (r - l + 1) / 2;if (nums[mid] <= target) l = mid;else r = mid - 1;}if (nums[r] != target) return -1;return r;}

二、思路二:红蓝法二分

大家可以看看我之前的文章

https://blog.csdn.net/qq_73435980/article/details/134771467

三、模板题

1、二分查找

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
class Solution {
public:int search(vector<int>& nums, int target) {sort(nums.begin(), nums.end());int left = 0, right = nums.size();while (left < right) {int mid = (left + right) / 2;if (nums[mid] < target)left = mid + 1;else if (nums[mid] > target)right = mid;elsereturn nums[mid] == target ? mid : -1;}return -1;}
};

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

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/

给你一个按照非递减顺序排列的整数数组 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]
class Solution {
public:int FindLeft(vector<int>& nums, int target){int l = 0, r = nums.size() - 1;while (l < r){int mid = l + (r - l) / 2;if (nums[mid] < target) l = mid + 1;else r = mid;}if (nums[l] != target) return -1;return l;}int FindRight(vector<int>& nums, int target){int l = 0, r = nums.size() - 1;while (l < r){int mid = l + (r - l + 1) / 2;if (nums[mid] <= target) l = mid;else r = mid - 1;}if (nums[r] != target) return -1;return r;}vector<int> searchRange(vector<int>& nums, int target) {if (nums.size() == 0) return { -1, -1 };int a = FindLeft(nums, target);int b = FindRight(nums, target);vector<int> ans = { a, b };return ans;}
};

http://www.mrgr.cn/news/41594.html

相关文章:

  • python引用计数
  • Windows+VSCode运行C/C++时生成的*.exe问题
  • 46. 全排列
  • 边缘自适应粒子滤波(Edge-Adaptive Particle Filter)的MATLAB函数示例,以及相应的讲解
  • C语言 | Leetcode C语言题解之第453题最小操作次数使数组元素相等
  • BBED标记坏块以及修复坏块
  • RabbitMQ 优点和缺点
  • netty之Netty与SpringBoot整合
  • PCL 点云直通滤波
  • Python | Leetcode Python题解之第452题用最少数量的箭引爆气球
  • 【理论科学与实践技术】数学与经济管理中的学科与实用算法
  • 谷歌最新发布:185个AI应用案例深度解析
  • Qt 概述
  • Spring Boot+VUE《班级综合测评管理系统》
  • 【漏洞复现】大华智慧园区综合管理平台 video 任意文件上传漏洞
  • 【CSDN语法】
  • 全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串
  • C++ | Leetcode C++题解之第452题用最少数量的箭引爆气球
  • PCL 点云高斯滤波
  • C++11 异步操作 std::future类