总结leetcode75中的二分查找算法题解题思路。
上一篇:力扣75——堆/优先队列
1 猜数字大小
题目:
猜数字游戏的规则如下:
每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
-1:我选出的数字比你猜的数字小 pick < num
1:我选出的数字比你猜的数字大 pick > num
0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字。
题解:
二分查找。用left
、right
分别记录左端点和右端点。然后计算出它们的平均值mid
,接着用guess(mid)
判断是大了还是小了。
class Solution {
public:
int guessNumber(int n) {
long int left = 1, right=n;
long int mid;
while(left<=right){
mid = (left+right)/2;
if (guess(mid)<0){
right = mid-1;
}
else if(guess(mid)>0){
left = mid +1;
}
else{
return mid;
}
}
return left;
}
};
2 咒语和药水的成功对数
题目:
给你两个正整数数组 spells 和 potions ,长度分别为 n 和 m ,其中 spells[i] 表示第 i 个咒语的能量强度,potions[j] 表示第 j 瓶药水的能量强度。
同时给你一个整数 success 。一个咒语和药水的能量强度 相乘 如果 大于等于 success ,那么它们视为一对 成功 的组合。
请你返回一个长度为 n 的整数数组 pairs,其中 pairs[i] 是能跟第 i 个咒语成功组合的 药水 数目。
题解:
先快速排序
,然后用upper_bound()
找到第一个成功的数,这样就可以计算出每个咒语对应的成功组合数目了。
class Solution {
public:
vector<int> successfulPairs(vector<int> &spells, vector<int> &potions, long long success) {
sort(potions.begin(), potions.end());
for (auto &x : spells)
x = potions.end() - upper_bound(potions.begin(), potions.end(), (success - 1) / x);
return spells;
}
};
3 寻找峰值
题目:
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值
所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
题解:
二分查找。
用left
、right
分别记录左端点和右端点。然后计算出它们的中间值mid
。接着判断中间值,如果是峰值则return mid
,如果只大于右值,则在mid
的右边进行二分查找;如果小于右值,则在mid
的左边进行二分查找。
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int n = nums.size();
// 辅助函数,输入下标 i,返回一个二元组 (0/1, nums[i])
// 方便处理 nums[-1] 以及 nums[n] 的边界情况
auto get = [&](int i) -> pair<int, int> {
if (i == -1 || i == n) {
return {0, 0};
}
return {1, nums[i]};
};
int left = 0, right = n - 1, ans = -1;
while (left <= right) {
int mid = (left + right) / 2;
if (get(mid - 1) < get(mid) && get(mid) > get(mid + 1)) {
ans = mid;
break;
}
if (get(mid) < get(mid + 1)) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return ans;
}
};
4 爱吃香蕉的珂珂
题目:
珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。
珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 k 根。如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 h 小时内吃掉所有香蕉的最小速度 k(k 为整数)。
题解:文章来源:https://www.toymoban.com/news/detail-654568.html
class Solution {
public:
int minEatingSpeed(vector<int>& piles, int h) {
int low = 1;
int high = 0;
for (int pile : piles) {
high = max(high, pile);
}
int k = high;
while (low < high) {
int speed = (high - low) / 2 + low;
long time = getTime(piles, speed);
if (time <= h) {
k = speed;
high = speed;
} else {
low = speed + 1;
}
}
return k;
}
long getTime(const vector<int>& piles, int speed) {
long time = 0;
for (int pile : piles) {
int curTime = (pile + speed - 1) / speed;
time += curTime;
}
return time;
}
};
1-4解题总结
使用二分查找的场景:从一组有序特性的数据中查找某个值。
有序特性:不需要严格有序,像题目3,因为通过判断mid跟其左右的大小,就可以确定在其左边或右边一定有个峰值。文章来源地址https://www.toymoban.com/news/detail-654568.html
到了这里,关于力扣75——二分查找的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!