二分查找
[Algo] 二分查找
注:Algo系列基于左神算法教程,提供C++实现。
1. 经典算法
// 1. 经典二分查找:给定有序序列,查找val,存在返回(任一)索引,否则返回-1
int binarySearch(const vector<int> &v, int val)
{
if (v.size() == 0) return -1;
int left = 0, right = v.size() - 1, mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
// mid = left + (right - left) >> 1
if (v[mid] == val) return mid;
else if (v[mid] < val) left = mid + 1;
else right = mid - 1;
}
return -1;
}
2. 大于等于num的左边界
// 2. 给定有序序列和val,查找不小于val的最左位置,存在返回索引,否则返回-1
int leftNoLessThan(const vector<int> &v, int val)
{
if (v.size() == 0) return -1;
int left = 0, right = v.size() - 1, mid = 0, ans = -1;
while (left <= right)
{
mid = (left + right) / 2;
if (v[mid] >= val)
{
ans = mid;
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return ans;
}
3. 峰值点
// 3. 给定序列(未必有序)(相邻元素不等),找出(任一)峰值点,返回索引
int findPeakIndex(const vector<int> &v)
{
if (v.size() == 1) return 0;
if (v[0] > v[1]) return 0;
if (v[v.size() - 1] > v[v.size() - 2]) return v.size() - 1;
// [1, v.size() - 2]必存在峰值点
int left = 1, right = v.size() - 2, mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (v[mid] < v[mid - 1]) right = mid - 1; // [left, mid - 1]必存在峰值点
else if (v[mid] < v[mid + 1]) left = mid + 1; // [mid + 1, right]必存在峰值点
else return mid;
}
return -1; // 永不执行
}