给定一个排好升序的数组A[1]、A[2]、……、A[n],其元素的值都两两不相等。请设计一高效的算法找出中间所有A[i] = i的下标。并分析其复杂度。
思路:
假设数组长度为len,则数组第一个元素的下标为0,最后一个元素的下标为len-1
1、当数组中第一个元素A[0]大于len-1时,因为数组中元素是升序,所以数组中其他元素都比len-1大。这种情况下A[i]不可能等于i。
2、当数组中最后一个元素A[len-1]小于0时,因为数组中元素是升序,所以数组中其他元素都比0小。这种情况下A[i]不可能等于i。
只有序列A[0]到A[len-1]与序列0到len-1有重叠部分时,A[i]才有可能等于i。
开始时left=0,right=len-1;
med=(left+right)/2;
判断A[med]==med;
zai
查找函数:
#include<iostream>
using namespace std;
typedef double ElemType;
void find(ElemType *arr,int left,int right )
{
if(right<left||arr==NULL)//当右下标小于左下标,函数返回。
return;
if(arr[right]<left||arr[left]>right)
//当数组最后一个值小于左下标
//或者数组最后一个值大于右下标。
//函数返回。
return ;
int med=(left+right)/2;
if(arr[med]==med)
cout<<med<<" ";
find(arr,left,med-1);//递归左边区域
find(arr,med+1,right);//递归右边区域
}
测试用例及输出数组元素函数:
void print(ElemType * arr,int len)
{
for(int i=0;i<len;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
void test1()
{
cout<<"test1"<<endl;
ElemType arr[]={0};
int len=sizeof(arr)/sizeof(arr[0]);
print(arr,len);
find(arr,0,len-1);
cout<<endl;
}
void test2()
{
cout<<"test2"<<endl;
ElemType arr[]={1};
int len=sizeof(arr)/sizeof(arr[0]);
print(arr,len);
find(arr,0,len-1);
cout<<endl;
}
void test3()
{
cout<<"test3"<<endl;
ElemType arr[]={1,2,3,4,5,6};
int len=sizeof(arr)/sizeof(arr[0]);
print(arr,len);
find(arr,0,len-1);
cout<<endl;
}
void test4()
{
cout<<"test4"<<endl;
ElemType arr[]={0,1,3,4,5,7};
int len=sizeof(arr)/sizeof(arr[0]);
print(arr,len);
find(arr,0,len-1);
cout<<endl;
}
void test5()
{
cout<<"test5"<<endl;
ElemType arr[]={0,1,2,3.6,4.5,5};
int len=sizeof(arr)/sizeof(arr[0]);
print(arr,len);
find(arr,0,len-1);
cout<<endl;
}
主函数:
int main()
{
//ElemType arr[6]={0,1,3,3.8,4.9,5};
//ElemType arr[] = {0, 1};
//ElemType arr[] = {0, 1, 2, 3, 4, 5, 6, 7};
//ElemType arr[] = {-9, -8, -4, -2, 4, 5, 9};
test1();
test2();
test3();
test4();
test5();
return 0;
}
测试结果: