1 二分查找介绍
1.1 在有序数组中查找目标值
int bSearch(vector<int>& nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] == target)
{
return mid;
}
else if (nums[mid] < target)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return -1;
}
1.2 二分查找的变体--查找第一个值等于目标值的元素
int bSearch(vector<int>& nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] > target)
{
r = mid - 1;
}
else if (nums[mid] < target)
{
l = mid + 1;
}
else
{
if (mid == 0 || nums[mid - 1] != target)
{
return mid;
}
else
{
r = mid - 1;
}
}
}
return -1;
}
1.3 二分查找的变体--查找最后一个值等于目标值的元素
int bSearch(vector<int>& nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] > target)
{
r = mid - 1;
}
else if (nums[mid] < target)
{
l = mid + 1;
}
else
{
if (mid == nums.size() - 1 || nums[mid + 1] != target)
{
return mid;
}
else
{
l = mid + 1;
}
}
}
return -1;
}
1.4 二分查找变体--查找第一个大于等于给定值的元素
int bSearch(vector<int>& nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] >= target)
{
if (mid == 0 || nums[mid - 1] < target)
{
return mid;
}
else
{
r = mid + 1;
}
}
else
{
l = mid + 1;
}
}
return -1;
}
1.5 二分查找变体--查找最后一个小于等于给定值的元素
int bSearch(vector<int>& nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] > target)
{
r = mid - 1;
}
else
{
if (mid == nums.size() - 1 || nums[mid + 1] > target)
{
return mid;
}
else
{
l = mid + 1;
}
}
}
return -1;
}
1.6
2 题目
2.1 搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (nums[mid] == target)
{
return mid;
}
else if (nums[mid] < target)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return l > r ? l : r;
}
};
2.2 山峰数组的顶部
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
int l = 1, r = arr.size() - 2;
while (l <= r)
{
int mid = l + ((r-l)>>1);
if (arr[mid] > arr[mid+1] && arr[mid] > arr[mid-1])
{
return mid;
}
else if (arr[mid] < arr[mid+1])
{
l = mid + 1;
}
else if (arr[mid] > arr[mid+1])
{
r = mid - 1;
}
}
return -1;
}
};
2.3 有序数组中的单一元素
剑指 Offer II 070. 排序数组中只出现一次的数字
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
//方法一:o(n)
// int res = 0;
// for (auto& i:nums)
// res ^= i;
// return res;
//方法二:o(logn)
int n = nums.size();
if (n == 1)
return nums[0];
return helper(nums, 0, n-1);
}
int helper(vector<int>& nums, int left, int right)
{
if (left <= right)
{
int m = left + ((right - left) >> 1);
if ((m == 0 && nums[m] != nums[m+1]) ||
(m == nums.size()-1 && nums[m] != nums[m-1]) ||
(m+1 < nums.size() && m-1 >= 0 && nums[m] != nums[m+1] && nums[m] != nums[m-1]))
{
return nums[m];
}
else
{
int l = helper(nums, left, m-1);
if (-1 == l)
{
return helper(nums, m+1, right);
}
else
{
return l;
}
}
}
return -1;
}
};
2.4 按权重随机选择
//ttps://leetcode-cn.com/problems/cuyjEf/solution/li-yong-qian-zhui-he-er-fen-sou-suo-kuai-dsxm/
/*
先把权重数组中所有权重加起来得到权重之和,然后用每个权重除以权重之和,就能得到每个下标被选择的概率。
比方说权重数组为[1,2,3,4],权重之和是10,由于下标0对应的权重是1,那么选择0的概率是10%,选择下标1、2、3的概率分别是20%、30%和40%。
可以创建另一个和权重数组的长度一样的数组sums,新数组的第i个数值sum[i]是权重数组中前i个数字之和,
有了这个数组sums就能很方便有根据等概率随机生成的数字p按照权重比例选择下标。
比方说,累加权重数组[1,2,3,4]中的权重得到的数组sums为[1,3,6,10]。有了这个累加权重的数组之后,
如果0到9之间的随机数p<1,那么选择0;
如果1<=p<3,那么选择1;
如果3<=p<6,那么选择2;
如果6<=p<10,那么选择3;
也就是说随机生成p之后,先顺序扫描累加权重数组sums找到第一个大于p的值,然后选择它对应的下标
*/
class Solution {
public:
vector<int> data;
int sum;
Solution(vector<int>& w) {
sum = 0;
for(auto& v:w)
{
sum += v;
data.push_back(sum);
}
}
int pickIndex() {
int target = rand() % sum;
int l = 0, r = data.size()-1;
//找到第一个大于 target 的值
while(l <= r)
{
int mid = l + ((r - l) >> 1);
if(data[mid] > target)
{
if (mid == 0 || data[mid - 1] <= target)
{
return mid;
}
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/
2.5 求平方根
//https://leetcode-cn.com/problems/sqrtx/solution/acm-xuan-shou-tu-jie-leetcode-sqrtx-by-r-p8fx/
class Solution {
public:
int mySqrt(int x) {
int l = 1, r = x, res = 0;
while (l <= r)
{
int m = l + ((r - l) >> 1);
// if (m * m <= x) 当m比较大时会溢出
if (m <= x/m)
{
res = m;
l = m + 1;
}
else
{
r = m - 1;
}
}
return res;
}
};
2.6 狒狒吃香蕉
class Solution {
public:
int minEatingSpeed(vector<int>& piles, int H) {
int lo = 1, hi = *max_element(piles.begin(), piles.end());
while (lo < hi)
{
int mi = lo + (hi - lo) / 2;
if (!possible(piles, H, mi))
lo = mi + 1;
else
hi = mi;
}
return lo;
}
// Can Koko eat all bananas in H hours with eating speed K?
bool possible(vector<int>& piles, int H, int K)
{
int time = 0;
for (int p: piles)
time += (p - 1) / K + 1;//向上取整
return time <= H;
}
};
2.7
2.8
2.9
2.10
2.11