【二分查找】
1. 基本型:
因为我们初始化 right = nums.length - 1
所以决定了我们的「搜索区间」是 [left, right]
所以决定了 while (left <= right)
同时也决定了 left = mid+1 和 right = mid-1
因为我们只需找到一个 target 的索引即可
int BinarySearch(int a[],int size,int key)
{
int left = 0, right = size - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] == key) return mid;
else if (a[mid] < key) left = mid + 1;
else right = mid - 1;
}
return -1;
}
2. 左侧边界:
查找第一个与key相等的元素,也就是说等于查找key值的元素有很多,返回这些元素最左边的元素的下标。
(当找到目标时,不会立即返回,而是收紧右边界)
//查找第一个与key相等的元素
int BinarySearch(int a[],int size,int key)
{
int left = 0, right = size - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] >= key) right = mid - 1;
else left = mid + 1;
}
if (left < size&&a[left] == key)
{
return left;
}
return -1;
}
查找第一个等于或者大于key的元素,查找第一个等于或者大于key的元素,也就是说查找key值的元素有好多个
,返回这些元素最左边元素的下标;如果没有等于key值的元素,则返回大于key的最左边元素的下标。
//查找第一个等于或者大于key的元素
int BinarySearch(int a[],int size,int key)
{
//如果a[right]<key,则找不到等于或者大于key的值,直接返回-1
int left = 0, right = size - 1;
if (a[right] < key) return -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] >= key) right = mid - 1;
else left = mid + 1;
}
return left;
}
查找第一个大于key的元素。查找第一个大于key的值,也就是说返回大于key的最左边元素的下标。
//查找第一个大于key的元素
int BinarySearch(int a[],int size,int key)
{
//如果a[right]<=key,则找不到大于key的值,直接返回-1
int left = 0, right = size - 1;
if (a[right] <= key) return -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] > key) right = mid - 1;
else left = mid + 1;
}
return left;
}
3. 右侧边界:
查找最后一个与key相等的元素,也就是等于查找key值的元素有好多个,返回这些元素最右边元素的下标。
(当找到目标时,不会立即返回,而是收紧左边界)
//查找最后一个与key相等的元素
int BinarySearch(int a[],int size,int key)
{
int left = 0, right = size - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] <= key) left = mid + 1;
else right = mid - 1;
}
if (right >=0 && a[right] == key)
{
return right;
}
return -1;
}
查找最后一个等于或者小于key的元素。查找最后一个等于或者小于key的元素,也就是说等于查找key值有很多
,返回这些元素最右边的元素的下标;如果没有等于key值的元素,则返回小于key值的最右边元素的下标。
//查找最后一个等于或者小于key的元素
int BinarySearch(int a[],int size,int key)
{
//如果a[left]>key,则找不到等于或者小于key的值,直接返回-1
int left = 0, right = size - 1;
if (a[left]>key) return -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] > key) right = mid - 1;
else left = mid + 1;
}
return right;
}
查找最后一个小于key的元素。查找最后一个小于key的元素,也就是说返回小于key的最右边的元素下标。
//查找最后一个小于key的元素
int BinarySearch(int a[],int size,int key)
{
//如果a[left]>=key,则找不到=小于key的值,直接返回-1
int left = 0, right = size - 1;
if (a[left]>=key) return -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (a[mid] >= key) right = mid - 1;
else left = mid + 1;
}
return right;
}
题目
- 基本型:540. 有序数组中的单一元素
/*
给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
示例 1:
输入: nums = [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:
输入: nums = [3,3,7,7,10,11,11]
输出: 10
*/
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = 0;
int len = nums.size();
int right = len - 1;
while(left <= right){
int mid = left + (right - left)/2;
int flag = mid % 2;
if((!flag && mid + 1 < len && nums[mid] == nums[mid+1])
|| (flag && mid - 1 >= 0 && nums[mid] == nums[mid-1]))
left = mid + 1;
else if((!flag && mid - 1 >= 0 && nums[mid] == nums[mid-1])
|| (flag && mid + 1 < len && nums[mid] == nums[mid+1]))
right = mid - 1;
else
return nums[mid];
}
return -1;
}
};
- 基本型:153. 寻找旋转排序数组中的最小值
// 写的太恶心了,待优化
class Solution {
public:
int findMin(vector<int>& nums) {
int left = 0;
int right = nums.size()-1;
if(right == 0)
return nums[0];
while(left <= right){
int mid = left + (right - left)/2;
if(mid -1 >= 0 && nums[mid-1] > nums[mid])
return nums[mid];
if(nums[mid] >= nums[left] && nums[mid] >= nums[right])
left = mid + 1;
else if(nums[mid] <= nums[left] && nums[mid] <= nums[right])
right = mid - 1;
else if(nums[mid] <= nums[left] && nums[mid] >= nums[right])
return nums[right];
else
return nums[left];
}
return nums[left];
}
};
- 右边界:744. 寻找比目标字母大的最小字母
class Solution {
public:
char nextGreatestLetter(vector<char>& letters, char target) {
int left = 0;
int right = letters.size();
while(left < right){
int mid = left + (right - left) / 2;
if(letters[mid] > target)
right = mid;
else
left = mid + 1;
}
if(left == letters.size())
return letters[0];
return letters[left];
}
};
- 左右边界:34. 在排序数组中查找元素的第一个和最后一个位置
class Solution {
public:
int lower_target(vector<int>& nums, int target){ // 左边界
int left = 0;
int right = nums.size();
while(left < right){
int mid = left + (right - left)/2;
if(nums[mid] >= target)
right = mid;
else
left = mid + 1;
}
// cout << left << " " << right << endl;
if(left >= nums.size() || (left >= 0 && nums[left] != target))
return -1;
return left;
}
int upper_target(vector<int>& nums, int target){ // 右边界
int left = 0;
int right = nums.size();
while(left < right){
int mid = left + (right - left)/2;
if(nums[mid] > target)
right = mid;
else
left = mid + 1;
}
// cout << left << " " << right << endl;
if(left-1 >= nums.size() || (left-1 >= 0 && nums[left-1] != target))
return -1;
return left - 1;
}
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size() > 0)
return {lower_target(nums,target), upper_target(nums,target)};
else
return {-1,-1};
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界