题目一:统计一个数字在排序数组中出现的次数。
解法一:
利用C++ stl的二分查找
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
auto resultPair = equal_range(data.begin(), data.end(),k);
return resultPair.second - resultPair.first;
}
};
int GetNumberOfK(vector<int> data, int k) {
//直接使用lower_bound和upper_bound可以解决
auto low = lower_bound(data.begin(), data.end(), k);
auto high = upper_bound(data.begin(), data.end(), k);
return high - low;
}
解法二:
看见有序,肯定就是二分查找了,算法比较简单,不多说,值得一提的是,不要拘泥于递归,要会循环写法。
//暴力匹配,时间复杂度O(n)
//观察数组本身的特性可以发现,
//排序数组这样做没有充分利用数组的特性,
//可以使用二分查找,找出数据,然后进行左右进行统计
//具体算法设计:二分查找找到k的所在位置
// 在原数组里面分别左右对k的出现次数进行统计
class Solution {
public:
int BinarySearch(vector<int> data, int low, int high, int k)
{
while (low <= high)
{
int m = (low + high) / 2;
if (data[m] == k)
return m;
else if (data[m] < k)
low = m + 1;
else
high = m - 1;
}
return -1;
}
int GetNumberOfK(vector<int> data, int k)
{
if (data.size() == 0)
return 0;
int len = data.size();
int keyIndex = 0;
keyIndex = BinarySearch(data, 0, len - 1, k);
if (keyIndex == -1)
return 0;
int sum = 1;
int m = keyIndex - 1;
int n = keyIndex + 1;
while (m >= 0 && data[m] == k)
{
m--;
sum++;
}
while (n < len && data[n] == k)
{
n++;
sum++;
}
return sum;
}
};
以下两题均是基于二分查找法:
题目二:0 ~ n-1 中缺失的数字
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1范围内的n个数字中有且只有一个数字不在该数组中,请找出该数字。
//如果中间元素的值和下标相等,那么下一轮查找只需要查找右半边;
//如果中间元素的值和下标不相等,并且它前面一个元素和它的下标相等,这意味着
//这个中间的数字正好是第一个值和下标不相等的元素,它的下标就是数组中不存在
//的数字;
//如果中间元素的值和下标不相等,并且它前面一个元素和它的下标不相等,这意味着
//下一轮查找我们只需要在左半边查找即可
int GetMissingNumber(vector<int> numbers, int length)
{
if (numbers.size() == 0)
return -1;
int left = 0;
int right = length - 1;
while (left <= right)
{
int middle = (left + right) >> 1;
if (numbers[middle] != middle)
{
if (middle == 0 || numbers[middle - 1] == middle - 1)
return middle;
right = middle - 1;
} else
left = middle + 1;
}
if (left == length)
return length;
}
题目三:数组中数值和下标相等的元素。
假设一个单调递增的数组里边的每个元素都是整数并且是唯一的。请实现一个函数,找出数组中任意一个数值等于其下标的元素。例如在数组{-3,-1,1,3,5}中,数字3和它的下标相等。
思路:如果第i个数字的值大于i,那么它右边的数字都大于对应的下标;如果第i个数字的值小于i,那么它左边的所有数字的值都小于对应的下标
int GetNumberSameAsIndex(vector<int> numbers, int length)
{
if (numbers.size() == 0)
return -1;
int left = 0;
int right = length - 1;
while (left <= right)
{
int middle = left + ((right - left) >> 1);
if (numbers[middle] == middle)
return middle;
if (numbers[middle] > middle)
right = middle - 1;
else
left = middle + 1;
}
return -1;
}