问题:
找出一个有序(字典序)字符串数组中arr中值等于字符串v的元素的序号,如果有多个元素满足这个条件,则返回其中序号最大的。
分析:
二分查找的细节确实很多啊。~~(╯﹏╰)b
我就不实现这个问题了。我主要实现后面几个小题。
给定一个有序(不降序)数组arr,求最大的i使得arr[i]等于v,不存在则返回-1。
我自己写的时候,跟书上犯了一模一样的错误…..
int bisearch_findMaxIdx_wrong(int* arr, int b, int e, int key){
int minIdx = b, maxIdx = e, midIdx;
while (minIdx < maxIdx){
midIdx = minIdx + (maxIdx - minIdx) / 2;
if (arr[midIdx] <= key){
minIdx = midIdx;
}
else{
maxIdx = midIdx-1;
}
}
if (arr[maxIdx] == key){
return maxIdx;
}
else if (arr[minIdx] == key){
return midIdx;
}
else{
return -1;
}
}
在写循环(或者递归)程序的时候,特别要注意:初始条件、转换、终止条件!!!!
我也没有考虑到循环的终止条件有可能无法到达。
测试数据与函数调用:
int arr[] = { 1, 3, 3, 4, 4, 7, 8 };
int idx = bisearch_findMaxIdx1(arr,0,6,3);
当minIdx=1,maxIdx=2
=>midIdx=1,arr[midIdx]<=3
=>minIdx=midIdx=1,maxIdx=2
程序进入了死循环
对于循环结束有两种情况:
1.若minIdx为偶数则minIdx==maxIdx
2.minIdx==maxIdx-1
我们可以将maxIdx=midIdx-1,改为maxIdx=midIdx,这样可以避免出现minIdx==maxIdx。
代码:
//给定一个有序数组,求任意一个i使得arr[i]等于v,不存在则返回-1
int bisearch(int* arr,int b,int e,int key){
int l = b, r = e,m;
while (l <= r){
m = l + (r - l) / 2;
if (arr[m] == key){
return m;
}
else if (arr[m]>key){
r = m - 1;
}
else{
l = m + 1;
}
}
return -1;
}
//找出有序数组中,最大的i使得arr[i]=key,不存在返回-1
int bisearch_findMaxIdx(int* arr,int b,int e,int key){
int minIdx = b, maxIdx = e, midIdx;
while (minIdx < maxIdx - 1){
midIdx = minIdx + (maxIdx - minIdx) / 2;
if (arr[midIdx] <= key){
minIdx = midIdx;
}
else{
maxIdx = midIdx;
}
}
if (arr[maxIdx] == key){
return maxIdx;
}
else if (arr[minIdx] == key){
return midIdx;
}
else{
return -1;
}
}
//找出有序数组中,最小的i使得arr[i]=key,不存在则返回-1
int bisearch_findMinIdx(int* arr,int b,int e,int key){
int minIdx = b, maxIdx = e, midIdx;
while (minIdx < maxIdx - 1){
midIdx = minIdx + (maxIdx - minIdx) / 2;
if (arr[midIdx] < key){
minIdx = midIdx;
}
else{
maxIdx = midIdx;
}
}
if (arr[minIdx] == key){
return minIdx;
}
else if (arr[maxIdx] == key){
return maxIdx;
}
else{
return -1;
}
}
//找出有序数组中,最大的i使得arr[i]<key,不存在则返回-1
int bisearch_findMaxIdx1(int* arr,int b,int e,int key){
int minIdx = b, maxIdx = e, midIdx;
while (minIdx < maxIdx - 1){
midIdx = minIdx + (maxIdx - minIdx) / 2;
if (arr[midIdx] < key){
minIdx = midIdx;
}
else{
maxIdx = midIdx;
}
}
if (arr[maxIdx] < key){
return maxIdx;
}
else if (arr[minIdx] < key){
return minIdx;
}
else{
return -1;
}
}
//找出有序数组中,最小的i使得arr[i]>key,不存在则返回-1
int bisearch_findMinIdx1(int* arr, int b, int e, int key){
int minIdx = b, maxIdx = e, midIdx;
while (minIdx < maxIdx - 1){
midIdx = minIdx + (maxIdx - minIdx) / 2;
if (arr[midIdx] <= key){
minIdx = midIdx;
}
else{
maxIdx = midIdx;
}
}
if (arr[minIdx]>key){
return minIdx;
}
else if (arr[maxIdx] > key){
return maxIdx;
}
else{
return -1;
}
}