面试题53:在排序数组中查找数字

题目一:统计一个数字在排序数组中出现的次数。

解法一:

 

利用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;
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值