LeetCode 剑指 Offer II 二分查找 专题总结
蜂信物联FastBee平台https://gitee.com/beecue/fastbee
阿里资料开源项目https://gitee.com/vip204888
百度低代码前端框架https://gitee.com/baidu/amis
OpenHarmony开源项目https://gitcode.com/openharmony
仓颉编程语言开放项目https://gitcode.com/Cangjie
int mid = ((right - left) >> 1) + left;
// 数组最小长度为3,不用担心越界问题
if(arr[mid] < arr[mid + 1]) {
left = mid + 1;
}else {
// arr[mid] > arr[mid + 1] 时记录
ans = mid;
right = mid - 1;
}
}
return ans;
}
};
==================================================================================
题目:
给定一个只包含整数的有序数组
nums,每个元素都会出现两次,唯有一个数只会出现一次,请找出这个唯一的数字。
示例:
输入: nums = [1,1,2,3,3,4,4,8,8]
输出: 2
输入: nums = [3,3,7,7,10,11,11]
输出: 10
提示:
-
1 <= nums.length <= 105 -
0 <= nums[i] <= 105
进阶: 采用的方案可以在 O(log n) 时间复杂度和 O(1) 空间复杂度中运行吗?
思路:
通过观察可以知道答案必然在数组下标为偶数的位置上,而且这个数组是升序的,可以使用二分查找
所以我们在查找时只需考虑偶数位,奇数跳过,知道这个即可用二分实现
O(log n)复杂度
nums[mid] == nums[mid + 1]代表这个不是答案且两个数一样,都跳过left = mid + 2;
nums[mid] < nums[mid + 1]代表这个数在答案右边也有可能是答案,ans保存
class Solution {
public:
// 注释的奇数,偶数说的是数组下标
// 思路:答案必定在偶数位上,因为相同的两个数都相邻,所以可以根据数组下标以及相邻数大小判断答案在左边还是在右边
int singleNonDuplicate(vector& nums) {
// 这样就不用担心数组越界问题了
if(nums.size() == 1)
return nums[0];
int left = 0, right = nums.size() - 1;
int ans = 0;
while(left <= right) {
int mid = ((right - left) >> 1) + left;
// 答案一定在数组下标偶数位上,所以只考虑偶数位
if(mid & 1 == 1) mid–;
if(nums[mid] == nums[mid + 1]) {
// 如果这个数不是答案,相当于他右边也不是,直接跳过
left = mid + 2;
}else {
ans = mid;
right = mid - 1;
}
}
return nums[ans];
}
};
=============================================================================
题目:
给定一个正整数数组
w,其中w[i]代表下标i的权重(下标从0开始),请写一个函数pickIndex,它可以随机地获取下标i,选取下标i的概率与w[i]成正比。
例如,对于
w = [1, 3],挑选下标 0 的概率为1 / (1 + 3) = 0.25 (即,25%),而选取下标1的概率为3 / (1 + 3) = 0.75(即,75%)。
也就是说,选取下标
i的概率为w[i] / sum(w) 。
示例:
输入:
inputs = [“Solution”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”]
inputs = [[[1,3]],[],[],[],[],[]]
输出:
[null,1,1,1,1,0]
解释:
Solution solution = new Solution([1, 3]);
solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 1
solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。
由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:
[null,1,1,1,1,0]
[null,1,1,1,1,1]
[null,1,1,1,0,0]
[null,1,1,1,0,1]
[null,1,0,1,0,0]
…
诸若此类。
提示:
-
1 <= w.length <= 10000 -
1 <= w[i] <= 10^5 -
pickIndex将被调用不超过10000次
思路:
前缀和 + 二分查找
以权重数组 [1, 2, 3, 4] 为例,标 0 的概率为 10% ,下标 1 、2 、 3 的概率为 20% 、30% 和40%。先按等概率生成 1 ~ 10,则每个数字的概率的都为 10%。如果生成 1 则选择下标 0,概率为 10%;如果生成 2 或 3 则选择下标 1,概率为 20%;如果生成 4、5 或 6 则选择下标 2,概率为 30%;如果生成 7、8、9 或 10 则选择下标 3,概率为 40%。
用前缀和数组
pre存储,因为pre递增,所以二分查找pre数组
答案满足:
pre[mid - 1] < rand() <= pre[mid], (mid == 0)直接返回,防止越界
class Solution {
public:
vector pre;
Solution(vector& w) {
int sum = 0;
for(int i : w) {
sum += i;
pre.push_back(sum);
}
}
int pickIndex() {
int left = 0, right = pre.size() - 1;
// 取随机数
int target = rand() % pre.back() + 1;
while(left <= right) {
int mid = ((right - left) >> 1) + left;
if(target <= pre[mid] ) {
if(mid == 0 || target > pre[mid - 1])
return mid;
right = mid - 1;
}else {
left = mid + 1;
}
}
return -1;
}
};
=========================================================================
题目:
给定一个非负整数
x,计算并返回x的平方根,即实现int sqrt(int x)函数。
正数的平方根有两个,只输出其中的正数平方根。
如果平方根不是整数,输出只保留整数的部分,小数部分将被舍去。
示例:
输入: x = 8
输出: 2
解释: 8 的平方根是 2.82842…,由于小数部分将被舍去,所以返回 2
提示:
0 <= x <= 231 - 1
思路:
二分查找
mid * mid <= x,则答案在右边或本身,ans记录
mid * mid > x,则答案在左边
将
mid * mid <= x换成mid <= x / mid防止乘积过大,同时过滤0,防止除数为0
class Solution {
public:
int mySqrt(int x) {
// 防止除数为0
if(x == 0)
return 0;
int left = 1, right = x;
int ans = 0;
while(left <= right) {
int mid = ((right - left) >> 1) + left;
// 将原本的 mid * mid <= x 可能越界,所以换格式
if(mid <= x / mid) {
ans = mid;
left = mid + 1;
}else {
right = mid - 1;
}
}
return ans;
}
};
==========================================================================
题目:
狒狒喜欢吃香蕉。这里有
N堆香蕉,第i堆中有piles[i]根香蕉。警卫已经离开了,将在H小时后回来。
狒狒可以决定她吃香蕉的速度
K(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉K根。如果这堆香蕉少于K根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉,下一个小时才会开始吃另一堆的香蕉。
狒狒喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在
H小时内吃掉所有香蕉的最小速度K(K为整数)。
示例:
输入: piles = [3,6,7,11], H = 8
输出: 4
提示:
-
1 <= piles.length <= 10^4 -
piles.length <= H <= 10^9 -
1 <= piles[i] <= 10^9
思路:
速度取值[1, piles.max],因为速度至少为1,超过数组最大值也只能吃数组最大值那么多
然后对区间二分查找,
check(piles, mid)函数计算mid速度所用时间
一线互联网大厂Java核心面试题库

正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等已整理上传,感兴趣的朋友可以看看支持一波!
提示:
-
1 <= piles.length <= 10^4 -
piles.length <= H <= 10^9 -
1 <= piles[i] <= 10^9
思路:
速度取值[1, piles.max],因为速度至少为1,超过数组最大值也只能吃数组最大值那么多
然后对区间二分查找,
check(piles, mid)函数计算mid速度所用时间
一线互联网大厂Java核心面试题库
[外链图片转存中…(img-aDemRDPZ-1725192645028)]
正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等已整理上传,感兴趣的朋友可以看看支持一波!
更多推荐



所有评论(0)