接下来的这几个题目是以二分查找算法为基础,考察该算法的灵活应用 题目一: 解析: 在排序的数组中查找数字,我们首先相当的是二分查找.然后要统计target在数组中出现的次数,我们不妨找到第一个target的下标first,然后找到最后一个target的下标last,次数即为last-first+1. 代码:
int GetFirstK(vector<int> data, int k, int l, int r)
{
int mid = 0;
if (l > r)
return -1;
while (l <= r)
{
mid = l + ((r-l) >> 1);
if (data[mid] == k)
{
if (mid == 0 || (mid > 0 && data[mid-1] != k))
{
return mid;
}
else if (mid > 0 && data[mid-1] == k)
{
r = mid - 1;
}
}
else if (data[mid] > k)
{
r= mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
int GetLastK(vector<int> data, int k , int l, int r)
{
int mid = 0;
if (l > r)
return -1;
while (l <= r)
{
mid = l + ((r-l) >> 1);
if (data[mid] == k)
{
if (mid == data.size()-1 || (mid < data.size()-1 && data[mid+1] != k))
{
return mid;
}
else if (mid < data.size()-1 && data[mid+1] == k)
{
l = mid + 1;
}
}
else if (data[mid] > k)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
int GetNumberOfK(vector<int> data ,int k) {
if (0 == data.size())
return 0;
int len = data.size();
int first = GetFirstK(data, k, 0, len-1);
int last = GetLastK(data, k, 0, len-1);
cout << first << endl;
cout << last << endl;
if (first > -1 && last > -1)
{
return (last - first + 1);
}
return 0;
}
题目二: 分析: 方法1: 遍历数组,对数组求和为sum1; 利用求和公式对数字0~n-1求和为sum2, 缺失的数字即为sum2 - sum1. 方法2:: 在排序的数组中长度n-1,数字范围为0~n-1(n个).二分查找,碰到的第一个数字和它的下标不相等的即为缺失的数字;若相等, l = mid + 1 如: 长度为5, 数字范围为0~5 数字: 0 1 3 4 5 下标: 0 1 2 3 4 2即为缺失的数字.
代码:
int GetMissingNum(const int * num, int len)
{
if (num)
{
int l = 0;
int r = len - 1;
while (l <= r)
{
int mid = l + ((r-l) >> 1);
if (num[mid] != mid)
{
if (mid == 0 || (mid > 0 && num[mid-1] == mid - 1))
{
return mid;
}
else
{
r = mid - 1;
}
}
else
{
l = mid + 1;
}
}
}
return -1;
}
题目三: 解析: 排序数组中寻找数值等于下标的,用二分法.若数值等于下标,找到;若数值>下标,r = mid-1;若数值<下标,l = mid + 1; 代码:
int GetNumberSameAsIndex(const int * arr, int len)
{
if (arr)
{
int l = 0;
int r = len - 1;
while (l <= r)
{
int mid = l + ((r-l) >> 1);
if (arr[mid] == mid)
{
return mid;
}
else if (arr[mid] > mid)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
}
return -1;
}
|