3.11 程序改错(二分查找)

问题:

找出一个有序(字典序)字符串数组中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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值