二分查找有很多变化的题型,现在来总结一下,都是二分查找的变化题型。由于时间伧俗,就直接上代码了,如有问题或者不懂的地方欢迎留言交流。
题目1 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。
如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
int SearchValue(const int *br,int n, const int val);
参数说明: br 指向连续空间。
n 元素的个数
val 查询的数据
返回值: -1 没有找到, 如果找到返回数值在数组中的下标。
问题2: 如果数据有重复,如何找到最left 端的数据?
问题3: 连续空间存储的数据有可能是升序,也有可能是降序,你如何解决?
#include<iostream>
#include<vector>
using namespace std;//C语言
void Show(const int* str,int len)//打印
{
int i = 0;
for (i = 0; i < len; ++i)
{
cout << str[i] << endl;
}
}int SearchValue(const int *br, int n, const int val)//查找
{
int left = 0;//左边界
int right = n - 1;//右边界
int pos = -1;
while (left <= right)//小于等于,假如是小于的话,就少了一个元素比较
{
int mid = (right - left ) / 2 + left;//加left防止越界
if (val < br[mid])
{
right = mid - 1;
}
else if (val > br[mid])
{
left = mid + 1;
}
else
{
while (left < mid && val == br[mid - 1]) --mid;//出现重复的数字,得到第一个
pos = mid;
break;//退出
}}
return pos;
}int main()
{
int br[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13 };
int len1 = sizeof(br) / sizeof(br[0]);
int pos = SearchValue(br, len1, 4);
cout << pos << endl;
Show(br, len1);
return 0;
}//c++实现
int FindValue1(const vector<int>&vec, int val)
{
int right = vec.size() - 1;
int left = 0;
int pos = -1;
while (left <= right)
{
int mid = (right - left + 1) / 2 + left;
if (val < vec[mid])
{
right = mid - 1;
}
else if (val > vec[mid])
{
left = mid + 1;
}
else
{
while (left < mid && vec[mid - 1] == val) --mid;//如果有重复的值
pos = mid;
break;
}
}
return pos;
}
int FindValue2(const vector<int>&vec, int val)
{
int right = vec.size() - 1;
int left = 0;
//int pos = -1;
while (left <= right)
{
int mid = (right - left + 1) / 2 + left;
if (val < vec[mid])
{
right = mid - 1;
}
if (val > vec[mid])
{
left = mid + 1;
}
/*if (val == vec[mid])//左边第一个
{
right = mid - 1;
}*/
if (val == vec[mid])//右边最后一个
{
left = mid + 1;
}
}
/*if (left < 0 || vec[left] != val)//有大量连续相等的值,返回最左边的一个位值
{
left = -1;
}*/
if (right > (vec.size()-1) || vec[right] != val)//返回最右边的位值
{
right = -1;
}
return right;
}//这是降序的情况
int FindValue3(const vector<int>&vec, int val)
{
int right = vec.size() - 1;
int left = 0;
//int pos = -1;
while (left <= right)
{
int mid = (right - left + 1) / 2 + left;
if (val > vec[mid])
{
right = mid - 1;
}
if (val < vec[mid])
{
left = mid + 1;
}
/*if (val == vec[mid])//左边第一个
{
right = mid - 1;
}*/
if (val == vec[mid])
{
left = mid + 1;
}
}
/*if (left < 0 || vec[left] != val)//有大量连续相等的值,返回最左边的一个值
{
left = -1;
}*/
if (right > (vec.size() - 1) || vec[right] != val)//返回右边的值
{
right = -1;
}
return right;
}
void Show1(vector<int>&vec)
{
int len = vec.size();
for (int i = 0; i < len; ++i)
{
cout << vec[i] <<" "<< endl;
}
cout << endl;
}int main()
{int ar[] = { 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,56,67,78,89,90 };
int len = sizeof(ar) / sizeof(ar[0]);
vector<int> vec(ar,ar+len);
int pos = FindValue2(vec,12);
Show1(vec);
cout << pos << endl;int br[] = { 89,78,56,54,43,32,21,12,12,12,12,12,12,12,12,12,12,12,12 };
int len = sizeof(br) / sizeof(br[0]);
vector<int> vec1(br, br + len);
int pos2 = FindValue2(vec1, 12);
Show1(vec);
cout << pos2 << endl;
return 0;
}
问题4: 寻找旋转排序数组中的最小值
假设升序排序的数组在预先未知的某个点上进行了旋转。
例如: 数组 {10,11,12,13,14,15,16,17} 可能变为 [14,15,16,17,10,11,12,13};
请找出其中最小的元素。假设数组中不存在重复元素.
int FindMin(const vector<int>&vec)
{
int left = 0;
int right = vec.size() - 1;
int value = vec[0];
while (left <= right)
{
int mid = (right - left) / 2 + left;
if (value > vec[mid])
{
value = vec[mid];//这是记录最小的值,这是改变的地方
right = mid - 1;
}
else if (value < vec[mid])
{
left = mid + 1;
}
else
{
value = vec[mid];
break;
}
}
return value;
}
int main()
{
//const int ar[] = { 11,12,13,6,7,8,9,10 };
//const int ar[] = { 11,12,13,5,6,7,8,9,10 };
//const int ar[] = { 11,12,13,14,15,16,17,9,10 };
const int ar[] = { 11,11,11,11,12,13,14,15,16,17,8,8,8,8,8,9,10 };
int len = sizeof(ar) / sizeof(ar[0]);
vector<int>vec(ar, ar + len);
int value = FindMin(vec);
Show(vec);
cout << value << endl;
return 0;}
问题5: 查询重复的整型数。
给定一个包含 n + 1 个整数的数组 ar,其数字都在 1 到 n 之间(包括 1 和 n),
可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
例如: input : ar[]={1,3,4,2,5,2}
output: 2
input: ar[]={3,1,3,4,2}
output: 输出: 3
int Sum(int n)
{
int i = 1;
int sum = 0;
for (i; i <= n; ++i)
{
sum += i;
}
return sum;
}
//所有元素的和减去1~n的和就是多的元素
int FindValue4(const vector<int> &vec)
{
int len = vec.size();
int sum = Sum(len-1);
int tmp = 0;
for (int i = 0; i < len; ++i)
{
tmp += vec[i];
}
tmp = tmp - sum;
return tmp;
}int main()
{
const int ar[] = { 1,5,9,8,3,4,7,6,2,9,10};
int len = sizeof(ar) / sizeof(ar[0]);
vector<int>vec(ar, ar + len);
int value = FindValue4(vec);
Show(vec);
cout << value << endl;
return 0;
}