前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是五月集训第九天:二分查找
一、练习题目
704. 二分查找
35. 搜索插入位置
剑指 Offer 53 - I. 在排序数组中查找数字 I
911. 在线选举
二、一点感悟
今天的二分查找题目是最早接触leetcode时候开始刷的,今天看完视频再刷再练还是学到了新东西,就比如今天这个二分模板,而且彻底理解之前错了很多次的35题插入位置,很多题解也是写的 nums[mid]>= target
这么做的含义,确实有一种通畅感。最后唠叨一下,跟着写了九天:个人感觉练就有用的。
// 大于等于target的数组下标模板
int bSearch(vector<int>& nums, int n, int target) {
int l = 0, r = n - 1;
int ans = n;
while (l <= r)
{
int mid = (l + r) >> 1;
if(nums[mid] >= target) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
记录下自己35. 搜索插入位置辛酸史。
三、算法思路
- 1、704. 二分查找:二分查找的模板题目,算是入门二分查找必刷的一道。
- 2、35. 搜索插入位置:查找插入位置实际上就是要找大于等于target数组中最小的下标~。
- 3、剑指 Offer 53 - I. 在排序数组中查找数字 I:把二分模板改一下。
- 4、911. 在线选举:二分查找。
三、源码剖析
// 704. 二分查找
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
int l = 0, r = n - 1;
while (l <= r){
int mid = l + (r - l) / 2;
if (nums[mid] > target) //(1)
r = mid - 1;
else if (nums[mid] < target) //(2)
l = mid + 1;
else //(3)
return mid;
}
return -1;
}
};
// 使用了模板:大于等于target的数组最小下标
class Solution {
public:
int bSearch(vector<int>& nums, int n, int target) {
int l = 0, r = n - 1;
int ans = n;
while (l <= r)
{
int mid = (l + r) >> 1;
if(nums[mid] >= target) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
int search(vector<int>& nums, int target) {
int n = nums.size();
int index = bSearch(nums, n, target);
if(index == n) {
return -1;
} else if(nums[index] != target) {
return -1;
}
return index;
}
};
- 1、能二分的前提数组是有序的,大于target收缩右边界;
- 2、小于target收缩左边界;
- 3、能找到就返回下标,否则返回-1。
// 35. 搜索插入位置
class Solution {
public:
int bSearch(vector<int>& nums, int n, int target) {
int l = 0, r = n - 1;
int ans = n;
while (l <= r)
{
int mid = (l + r) >> 1;
if(nums[mid] >= target) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
int searchInsert(vector<int>& nums, int target) {
return bSearch(nums, nums.size(), target);
}
};
- 1、绝对值相等那ans保存数值更大的那个;
- 2、绝对值不等而且是小的情况下,ans就更新为更小的数值。
// 剑指 Offer 53 - I. 在排序数组中查找数字 I
class Solution {
public:
int bSearch(vector<int>& nums, int n, int target) {
int l = 0, r = n - 1;
int ans = n;
while (l <= r)
{
int mid = (l + r) >> 1;
if(nums[mid] >= target) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
int search(vector<int>& nums, int target) {
int n = nums.size();
int index = bSearch(nums, n, target);
if(index == n) {
return 0;
} else if(nums[index] != target) {
return 0;
}
return bSearch(nums, n, target + 1) - index; //(1)
}
};
- 1、先找到target最小下标index,再去找targe + 1的最小下标index1,index1 - index就是重复元素的个数了。
// 911. 在线选举
class TopVotedCandidate {
vector<int> vec; //记录每个时间点的领先者
vector<int> time; // 记录时间
public:
TopVotedCandidate(vector<int>& persons, vector<int>& times) {
unordered_map<int, int> mp; // 记录实时的票数,后续加票、查询
int top = -1;
mp[-1] = -1;
for (int i = 0; i < times.size(); i++)
{
int p = persons[i];
mp[p]++;
if (mp[p] >= mp[top])
top = p;
vec.emplace_back(top);
}
this->time = times;
}
int q(int t) {
int left = 0, right = time.size() - 1;
while (left < right)
{
int mid = left + (right - left + 1) / 2;
if (time[mid] > t)
right = mid - 1;
else
left = mid;
}
return vec[right];
}
};
/**
* Your TopVotedCandidate object will be instantiated and called as such:
* TopVotedCandidate* obj = new TopVotedCandidate(persons, times);
* int param_1 = obj->q(t);
*/