五月集训 (第09天) —— 二分查找
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五月集训 (第09天) —— 二分查找相关的知识,希望对你有一定的参考价值。
文章目录
前言
此为《英雄算法联盟:算法集训》的内容,具体内容详见:知识星球:英雄算法联盟。加入星球后,即可享用星主 CSDN付费专栏 免费阅读 的权益。
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
希望大家先自己思考,如果实在没有想法,再看下面的算法思路,如果有思路但是写不出来,可以参考朋友圈中其他人的代码,总有一款是适合你的,关注一下他,取其之长,补给之短。
今天集训的内容是:二分查找
前两题较为简单,第三题思路稍微转换一下,第四题想了一段时间,是一种预处理的思想。
一、练习题目
题目链接 | 难度 |
---|---|
35. 搜索插入位置 | ★☆☆☆☆ |
704. 二分查找 | ★☆☆☆☆ |
剑指 Offer 53 - I. 在排序数组中查找数字 I | ★★☆☆☆ |
911. 在线选举 | ★★★☆☆ |
二、算法思路
1、搜索插入位置
(1)实现一个 int bSearch(int *nums, int n, int target)
函数,代表从一个数组中找到大于等于 target 的最小下标;
(1.1)用一个 ans 来存储这个下标,一开始等于数组的右边界,代表如果不存在大于等于 target 的数,则下标就是这个右边界,即右边界是一个无限大的数;
(1.2)nums[mid] >= target 表示 mid 是一个满足条件的解,所以我们把 mid 存储下来,继续在 mid 左边尝试找更小的;
int bSearch(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(int* nums, int numsSize, int target)
return bSearch(nums, numsSize, target);
2、二分查找
(1)沿用上一题实现的 bsearch ,如果返回的下标 等于右边界 或者 对应位置不等于 target 则直接返回 -1;否则,返回之前找到的下标。
int bSearch(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(int* nums, int n, int target)
// >= target 的最小下标
int index = bSearch(nums, n, target);
if (index == n)
return -1;
else if(nums[index] != target)
return -1;
return index;
3、剑指 Offer 53 - I. 在排序数组中查找数字 I
(1)还是沿用 bsearch 函数,先找一次大于等于 target 最小下标 index;
(2)如果 index 等于右边界或者对应数组的值不等于 target 直接返回 0;
(3)否则,继续调用 bsearch 找大于等于 target+1 最小下标 index1,返回结果 index1 - index;
// 大于等于 target 的最小下标
int bSearch(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(int* nums, int n, int target)
int index = bSearch(nums, n, target);
if(index == n || nums[index] != target)
return 0;
return bSearch(nums, n, target + 1) - index;
4、在线选举
(1)预处理每个时间点的赢家;
(2)对于每次询问,二分查找小于等于给定时间 t 的最大下标,通过下标去索引赢家;
#define maxn 5001
typedef struct
int p[maxn], t[maxn], win[maxn];
int cnt[maxn];
int size;
TopVotedCandidate;
TopVotedCandidate* topVotedCandidateCreate(int* persons, int personsSize, int* times, int timesSize)
TopVotedCandidate *obj = (TopVotedCandidate *)malloc(sizeof(TopVotedCandidate));
memset(obj->cnt, 0, sizeof(obj->cnt));
int preMaxPerson = -1;
for(int i = 0; i < personsSize; ++i)
obj->p[i] = persons[i];
obj->t[i] = times[i];
++obj->cnt[ obj->p[i] ];
if(preMaxPerson == -1 || obj->cnt[ obj->p[i] ] >= obj->cnt[ preMaxPerson ] )
preMaxPerson = obj->p[i];
obj->win[i] = preMaxPerson;
obj->size = personsSize;
return obj;
int topVotedCandidateQ(TopVotedCandidate* obj, int t)
int l = 0, r = obj->size - 1;
int ans = -1;
while(l <= r)
int mid = (l + r) >> 1;
if(obj->t[mid] <= t)
ans = mid;
l = mid + 1;
else
r = mid - 1;
return obj->win[ans];
void topVotedCandidateFree(TopVotedCandidate* obj)
free(obj);
以上是关于五月集训 (第09天) —— 二分查找的主要内容,如果未能解决你的问题,请参考以下文章