零、前言——二分查找
条件:如果数组是有序数组、部分有序数组、或者局部有序数组,在这类数组中进行查找时,二分查找较为常用。时间复杂度O(logN)。二分查找的主要思路:设定两个指针start和end分别指向数组元素的首、尾,然后比较数组中间结点arry[mid]和待查找元素。如果待查找元素小于中间元素,说明待查找元素在数组的前半段,那么将end=mid-1,如果待查找元素大于中间元素,说明该元素在数组的后半段,将start=mid+1; 如果中间元素等于待查找元素,那么返回mid的值。
//统计一个数字在已经有序的数组中出现的次数。
int binary_search(vector<int> data, int len, int goal)
{
int low = 0;
int high = len - 1;
while (low <= high)
{
int middle = (high - low) / 2 + low; // 直接使用(high + low) / 2 可能导致溢出
if (data[middle] == goal)
return middle;
//在左半边
else if (data[middle] > goal)
high = middle - 1;
//在右半边
else
low = middle + 1;
}
//没找到
return -1;
}
int GetNumberOfK(vector<int> data, int k)
{
int count = 0;
int index;
int len = data.size();
index = binary_search(data, len, k);
if (index != -1)
{
count++;
for (int i = index - 1; i >= 0; i--)
{
if (data[i] == k)
{
count++;
}
}
for (int i = index + 1; i < len; i++)
{
if (data[i] == k)
{
count++;
}
}
}
return count;
}
void main()
{
vector<int> v = { 1, 2, 3, 3, 3, 3, 3, 3, 4, 5 };
cout << GetNumberOfK(v, 3);
}
//寻找第一个
int getFirstTarget(vector<int>& data, int target)
{
int length = data.size();
if (length <= 0)
{
return -1;
}
int pLeft = 0;
int pRight = length - 1;
while (pLeft <= pRight)
{
int index = (pLeft + pRight) / 2;
if (data[index] == target)
{
if ((index > 0 && data[index - 1] != target) || index == 0) //限制得到的是第一个target数字
{
return index;
}
else
pRight = index - 1;
}
else if (data[index] < target)
{
pLeft = index + 1;
}
else
{
pRight = index - 1;
}
}
return -1;
}
//寻找最后一个
int getLastTarget(vector<int>& data, int target)
{
int length = data.size();
if (length <= 0)
{
return -1;
}
int pLeft = 0;
int pRi