剑指offer53(二分的应用)

接下来的这几个题目是以二分查找算法为基础,考察该算法的灵活应用
题目一:
在这里插入图片描述
解析:
在排序的数组中查找数字,我们首先相当的是二分查找.然后要统计target在数组中出现的次数,我们不妨找到第一个target的下标first,然后找到最后一个target的下标last,次数即为last-first+1.
代码:

//找目标值第一次出现
int GetFirstK(vector<int> data, int k, int l, int r) //k即为目标
    {
        int mid = 0;
        if (l > r)
            return -1;
        while (l <= r)
        {
            mid = l + ((r-l) >> 1);
            if (data[mid] == k) //若找到
            {
                //是否为数组第一个数字或数组前一个数字不等于k
                if (mid == 0 || (mid > 0 && data[mid-1] != k))
                {
                    return mid;//找到了第一个目标值
                }
                //数组中前一个数字等于k
                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即为缺失的数字.

代码:

//0~n-1(数字范围) 数组长度为n-1  有序 
	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;
	 } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值