各种二分查找

二分查找

给定一个有序(不降序)数组arr。

1、求任意一个i使得arr[i]等于val,不存在则返回-1

2、求最小的i使得arr[i]等于val,不存在则返回-1

3、求最大的i使得arr[i]等于val,不存在则返回-1

4、求最大的i使得arr[i]小于val,不存在则返回-1

5、求最小的i使得arr[i]大于val,不存在则返回-1

一个错误的二分查找:

int bisearch(int *arr, int b, int e, int val)
{
    while(b<e)
    { 
        int mid = (b+e)>>2;
        if(arr[mid] <= val)
        {
            b = mid; 
        }
        else
        {
            e = mid-1; 
        } 
    }
    if(arr[e] == val)
    {
        return e; 
    } 
    else
    {
        return -1; 
    } 
}

下面通过构建测试用例来找出这个程序的问题

对于所有有效输入

在arr数组中查找元素val,对于问题123构建如下的测试用例。

arr数组

找到

未找到

空集

不存在

1

1个元素

2

3

多个元素

arr中含有一个val   含有多个

位于arr开头  4        5

结尾           6        7

中间           8        9

比最小的小            10

比最大的大            11

在范围内就是不含有    12

构建测试用例

1

int a1[] = {};

cout << bisearch(a, 0, sizeof(a1)/sizeof(int)-1, 8) << endl;

2

int a2[] = {8};

cout << bisearch(a, 0, sizeof(a2)/sizeof(int)-1, 8) << endl;

3

int a3[] = {10};

cout << bisearch(a, 0, sizeof(a3)/sizeof(int)-1, 8) << endl;

4

int a4[] = {1,2,3,4,5,6,7,7,7,7,7};

cout << bisearch(a, 0, sizeof(a4)/sizeof(int)-1, 1) << endl;

5

int a5[] = {1,1,1,2,3,4,5,6,7,7,7,7,7};

cout << bisearch(a, 0, sizeof(a5)/sizeof(int)-1, 1) << endl;

6

int a6[] = {1,2,3,4,5,6,7,7,7,7,7,8};

cout << bisearch(a, 0, sizeof(a6)/sizeof(int)-1, 8) << endl;

7

int a7[] = {1,2,3,4,5,6,7,7,7,7,7,8,8,8,8};

cout << bisearch(a, 0, sizeof(a7)/sizeof(int)-1, 8) << endl;

8

int a8[] = {1,2,3,4,5,6,7,7,7,7,7,8,8,8,10,10,12};

cout << bisearch(a, 0, sizeof(a8)/sizeof(int)-1, 6) << endl;

9

int a9[] = {1,2,3,4,5,6,7,7,7,7,7,8,8,8,10,10,12};

cout << bisearch(a, 0, sizeof(a9)/sizeof(int)-1, 8) << endl;

10

int a10[] = {2,3,4,5,6,7,7,7,7,7};

cout << bisearch(a, 0, sizeof(a10)/sizeof(int)-1, 1) << endl;

11

int a11[] = {2,3,4,5,6,7,7,7,7,7};

cout << bisearch(a, 0, sizeof(a11)/sizeof(int)-1, 12) << endl;

12

int a12[] = {2,3,4,5,7,7,7,7,7};

cout << bisearch(a, 0, sizeof(a12)/sizeof(int)-1, 6) << endl;

 

期望的测试结果

测试用例编号

问题1

问题2

问题3

1

-1

-1

-1

2

0

0

0

3

-1

-1

-1

4

0

0

0

5

0-2任意

0

2

6

11

11

11

7

11-14任意

11

14

8

5

5

5

9

11-13

11

13

10

-1

-1

-1

11

-1

-1

-1

12

-1

-1

-1

对于上面那个错误程序:测试样例4进入死循环,经过分析发现,(来自编程之美)


也就是说一种情况下没有缩小范围导致。

对每一种情况都缩小范围,可以得到题目1的如下代码:可以通过全部测试样例

//递归
int bisearch(int *arr, int s, int e, int val)
{
    if(s>e) return -1;
    int mid = s + ((e - s) >>1);
    if(arr[mid] == val) return mid;
    else if(arr[mid] < val) return bisearch(arr,mid+1, e, val);
    else return bisearch(arr,s, mid-1, val);
}
// 非递归
int bisearch(int *arr, int s, int e, int val)
{
    while(s<=e)
    {
        int mid = s + ((e-s)>>2);
        if(arr[mid]==val) return mid;
        else if(arr[mid]<val)  s=mid+1;
        else e=mid-1; 
    }
    return -1; 
}
//或者
int bisearch(int *arr, int s, int e, int val)
{
    /*
    循环结束有两种情况
    s为偶数  s=e
    s为奇数  s=e-1 
    */ 
    while(s < e-1)
    {
        int mid = s+((e-s)>>1);
        if(arr[mid]<=val)
        {
            s=mid; 
        }else{
              // 不需要e=mid-1 防止s=e 
            e=mid; 
        } 
    } 
    if(arr[s]==val)  return s;
    if(arr[e]==val)  return e;
    return -1; 
}

//第二题:
int bisearch(int *arr, int s, int e, int val)
{
    while(s <= e)
    {
        if(arr[s]==val)  return s; 
        int mid = s+((e-s)>>1);
        if(arr[mid]<val)
        {
            s=mid+1; 
        }else if(arr[mid]==val){
            e=mid; 
        } else{
            e=mid-1; 
        } 
    } 
    return -1; 
}
//第三题:
int bisearch(int *arr, int s, int e, int val)
{
    while(s <= e)
    {
        if(arr[e]==val) return e;
        int mid=s+((e-s-1)>>2)+1; // 尽量往后落,也就是3和4落在4 2和6仍然也落在4 
        if(arr[mid] < val)
            s=mid+1;
        else if(arr[mid] == val) 
            s=mid;
        else 
            e=mid-1; 
    } 
    return -1; 
}

对于4,5问题不存在找不到的情况,构建测试用例

arr

val

空集

任意1

1

相等2

大于3

小于 4

多个

小于最小5

等于最小 6

在中间相等不等8

等于最大 9

大于最大10

 

1

int a1[] = {};

cout << bisearch(a1, 0, sizeof(a1)/sizeof(int)-1, 8) << endl;

2

int a2[] = {8};

cout << bisearch(a2, 0, sizeof(a2)/sizeof(int)-1, 8) << endl;

3

int a3[] = {10};

cout << bisearch(a3, 0, sizeof(a3)/sizeof(int)-1, 8) << endl;

4

int a4[] = {5};

cout << bisearch(a4, 0, sizeof(a4)/sizeof(int)-1, 8) << endl;

5

int a5[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a5, 0, sizeof(a5)/sizeof(int)-1, 1) << endl;

6

int a6[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a6, 0, sizeof(a6)/sizeof(int)-1, 3) << endl;

7

int a7[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a7, 0, sizeof(a7)/sizeof(int)-1, 7) << endl;

8

int a8[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a8, 0, sizeof(a8)/sizeof(int)-1, 9) << endl;

9

int a9[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a9, 0, sizeof(a9)/sizeof(int)-1, 18) << endl;

10

int a10[] = {3,5,6,7,7,7,8,8,8,8,12,18};

cout << bisearch(a10, 0, sizeof(a10)/sizeof(int)-1, 20) << endl;

 

测试用例编号

问题4

问题5

1

-1

-1

2

-1

-1

3

-1

0

4

0

-1

5

-1

0

6

-1

1

7

2

6

8

9

10

9

10

-1

10

11

-1


//第四题
int bisearch(int *arr, int s, int e, int val)
{
    //求最大的i使得arr[i]小于val,不存在则返回-1
    while(s<=e){
        if(arr[e]<val) return e; 
        int mid = s+((e-s-1)>>1)+1;
        if(arr[mid]<val){
            s=mid; 
        } 
        else{
             e=mid-1; 
        }            
    } 
    return -1; 
}
//第五题
int bisearch(int *arr, int s, int e, int val)
{
    //求最小的i使得arr[i]大于val,不存在则返回-1
    while(s<=e){
        if(arr[s] > val) return s; 
        int mid = s + ((e-s)>>1); 
        if(arr[mid]<=val){
            s=mid+1; 
        } else{
            e=mid; 
        } 
    } 
    return -1; 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值