6、分别用递归和非递归实现二分查找算法
题目:用递归和非递归实现二分查找算法
分析:二分查找法也称为折半查找法,它的思想是每次都与序列的中间元素进行比较,二分查找的一个前提条件是数组是有序的。
/************************************************************************/
/* 非递归方法 */
/************************************************************************/
int BinarySearch(int a[],int n,int data)
{
if(a==NULL || n<=0)
return -1;
int begin=0;
int end=n-1;
while(begin <=end)
{
int mid=(begin+end)/2;
if(a[mid]==data)
return mid;
else if(a[mid] > data)
end=mid-1;
else
begin=mid+1;
}
return -1;
}
/************************************************************************/
/* 递归方法 */
/************************************************************************/
int BinarySearchRecursion(int a[],int data, int begin, int end)
{
if(begin > end)
return -1;
int mid=(begin+end)/2;
if(a[mid]==data)
return mid;
else if(a[mid] > data)
return BinarySearchRecursion(a,data,begin,mid-1);
else
return BinarySearchRecursion(a,data,mid+1,end);
}
int BinarySearch_Recursion(int a[],int n, int data)
{
if(a==NULL || n<=0)
return -1;
return BinarySearchRecursion(a,data,0,n-1);
}
7、在排序数组中,找出给定的数字出现的次数
题目:在有序数组中,找出给定数字的出现次数, 如[1,2,2,2,3]中2出现次数为3.
分析:该问题的解决方法可以在二分查找的基础上进行改进。设数组a为递增序列,需要查找的元素为data,为了求给定数字的出现次数,可以分别寻找data在a中最先出现的位置和最后出现的位置,然后就可求出数字的出现次数。
int BinarySearch(int a[],int n,int data, bool isLeft)
{
//isLeft标记值是否在左边
if(a==NULL || n<=0)
return -1;
int begin=0;
int end=n-1;
int last=-1;
while(begin <=end)
{
int mid=(begin+end)/2;
if(a[mid] > data)
end=mid-1;
else if(a[mid] < data)
begin=mid+1;
else
{
last=mid;
if(isLeft)
end=mid-1;
else
begin=mid+1;
}
}
return last;
}
int main()
{
int a[]={3,3,3,3,3,3,3,3,3,3,3,4,5,6,7,13,19};
int len=sizeof(a)/sizeof(a[0]);
int index1=BinarySearch(a,len,3,true);//求最先出现的位置
int index2=BinarySearch(a,len,3,false);//求最后出现的位置
cout << index1 << ' ' << index2 << endl;
cout << index2-index1+1 << endl;
}
8、计算两个有序整型数组的交集
题目:两个含有n个元素的有序(非降序)整型数组a和b(无重复元素),求出共同元素。
如:a=0 1 2 3 4 b= 1 3 5 7 9 a和b交集为{1,3}
分析:采用两路归并来遍历两个数组。设两个数组为a[n1] 和 b[n2] 分别从头遍历连个数组。若a[i]==b[i],则记录数据。若a[i]>b[i],则继续向后遍历b,若a[i]<b[i],则继续向后遍历a。直到一个数组遍历结束为止。
int mixed(int a1[],int n1, int a2[], int n2, int *m)
{
int i=0,j=0,k=0;
while(i<n1 && j <n2)
{
if(a1[i]==a2[j])
{
m[k++]=a1[i];
i++;
j++;
}
else if(a1[i]<a2[j])
i++;
else
j++;
}
return k;
}
9、找出数组中唯一的重复元素
题目:数组a[n],1至n-1这n-1个数存放在a[n]中,其中有一个数重复一次,找出这个重复的数,要求每个数组元素只能访问一次,不用辅助存储空间
分析:由于要求每个元素只能访问一次,可以采用数学求和法。因为只有一个元素重复一次,数也是连续的。对数组的所有项求和,然后减去1至n-1的和,即为重复数。
int FindDup(int a[], int n)
{
int sum1=0;
int sum2=0;
for(int i=0;i<n-1;i++)
{
sum1 +=(i+1);
sum2 +=a[i];
}
sum2 +=a[n-1];
return sum2-sum1;
}
10、判断一个数组中的数值是否连续相邻题目:一个整数数列,元素取值可能是0-65535中的任意一个数,相同数值不会重复出现,0是例外,可以反复出现,设计一个算法,当从该数列中随意选取5个数值时,判断这5个数值是否连续相邻。需要注意一下4点:
1、5个数值允许乱序 如 87 5 0 6
2、0可以通配任意数值,如8 7 5 0 6 中的0可以通配成9或4
3、0可以多次出现
4、全0算连续,只有一个非0算连续
分析:如果没有0的存在,要组成连续的数列,最大值和最小值的差距必须为4存在0的情况下,只要最大值和最小值的差距小于4就可以了,所以找出数列中非0的最大值和非0的最小值,如果非0最大值-非0最小值+1 <=5 则连续相邻。否则不连续相邻
bool isContinuous(int a[],int n)
{
int min=-1,max=-1;
for(int i=0;i<n;i++)
{
if(a[i]!=0)
{
if(min > a[i] || -1==min)
min=a[i];
if(max < a[i] || -1==max)
max=a[i];
}
}
if(max-min > n-1)
return false;
else
return true;
}