排序与查找(一): 二分查找

    比较简单,就不介绍了,代码中也有介绍与说明。

/**  

*@Title: BinarySearch.java

*@Package sortandsearch

*@Description: TODO

*@author peidong 

*@date 2017-5-5 上午9:16:33

*@version V1.0  

*/

packagesortandsearch;

 

/**

 * @ClassName: BinarySearch

 * @Description: 一些与二分查找相关的问题

 * @date 2017-5-5 上午9:16:33

 * 

 */

publicclass BinarySearch {

 

       /*问题1描述

       给一个已经排序的数组,其中有N个互不相同的元素。要求使用最小的比较次数找出其中的一个元素。

       (你认为二分查找在排序数组里找一个元素是最优的算法的吗?)*/

       /**

        *

       * @Title: binarySearch

       * @Description: 最基础的二分查找

       * @param @param arr 数组

       * @param @param start 开始位置

       * @param @param end   结束位置

       * @param @param key   查找的值

       * @param @return   

       * @return int   

       * @throws

        */

       public static int binarySearch(int[] arr,int start, int end, int key){

              int mid;

              while(start <= end){

                     mid = (start + (end -1))/2;

                     //第一次比较

                     if(arr[mid] == key)

                            return mid;

                     //第二次比较

                     if(arr[mid] > key)

                            end = mid - 1;

                     //第三次比较

                     else

                            start = mid +1;

              }

              return -1;

       }

      

       /*理论上,我们最多需要 logN+1 次比较。仔细观察,我们在每次迭代中使用两次比较,除了最后比较成

       功的一次。实际应用上,比较也是代价高昂的操作,往往不是简单的数据类型的比较。减少比较的次数也是

       优化的方向之一。*/

       /**

        *

       * @Title: binarySearch2

       * @Description: 改进的二分查找

       * @param arr

       * @param start

       * @param end

       * @param key

       * @return   

       * @return int   

       * @throws

        */

       public static int binarySearch2(int[]arr, int start, int end, int key){

              int mid;

              while(end - 1 >start){

                     mid = start + (end-1)/2;

                     if(arr[mid] <= key){

                            start = mid;

                     }else

                            end = mid;

              }

              if(arr[start] == key)

                     return start;

              else

                     return -1;

       }

      

       /*问题2描述

       给一个有N个互不相同的元素的已排序数组,返回小于或等于给定key的最大元素。 例如输入为 A = {-1, 2, 3, 5, 6, 8, 9, 10}  key = 7,应该返回6.

 

       分析:

 

       我们可以用上面的优化方案,还是保持一个恒等式,然后移动左右两个指针。最终 left指针会指向 小于或等于给定key的最大元素(根据恒等式A[l] <= key and A[r] > key)。

 

       - > 如果数组中所有元素都小于key,左边的指针left 会一直移动到最后一个元素。

 

       - > 如果数组中所有元素都大于key,这是一个错误条件,无答案。

 

       - > 如果数组中的所有元素都 <= key,这是最坏的情况根据下面的实现*/

      

       public static int floor(int[] arr, intstart, int end, int key){

              int mid;

              while(end - 1 > start){

                     mid = start + (end -1)/2;

                     if(arr[mid] <= key)

                            start = mid;

                     else

                            end = mid;

              }

              return arr[start];

       }

      

       //首次调用

       public static int floor(int[] arr, intlen, int key){

              //如果key比所有值都小

              if(key < arr[0])

                     return -1;

              //递归

              return floor(arr, 0, len, key);

       }

       /**

        *@Title: main

        *@Description: 测试

        *@param @param args   

        *@return void   

        *@throws

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              //问题一测试用例

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

//        int res1,res2;

//        res1 = binarySearch(arr,0,9,5);

//        res2 = binarySearch2(arr, 0, 5, 7);

//       System.out.printf("%d,%d",res1,res2);

       

        //问题二测试用例

        int[] arr1 = {-1, 2, 3, 5, 6, 8, 9,10};

        int res;

        res = floor(arr1, 7, 7);

        System.out.println(res);

       

       }

 

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值