剑指offer53(二分的应用)
Posted ~千里之行,始于足下~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指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;
}
以上是关于剑指offer53(二分的应用)的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 剑指Offer 53 - I 在排序数组中查找数字I[二分法] HERODING的LeetCode之路
剑指offer-面试题53_3-数组中数值和下标相等的元素-二分查找