二分法查找的算法

例一:

Search in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

因为rotate的缘故,当我们切取一半的时候可能会出现误区,所以我们要做进一步的判断。具体来说,假设数组是A,每次左边缘为l,右边缘为r,还有中间位置是m。在每次迭代中,分三种情况:
(1)如果target==A[m],那么m就是我们要的结果,直接返回;
(2)如果A[m]<A[r],那么说明从m到r一定是有序的(没有受到rotate的影响),那么我们只需要判断target是不是在m到r之间,如果是则把左边缘移到m+1,否则就target在另一半,即把右边缘移到m-1。
(3)如果A[m]>=A[r],那么说明从l到m一定是有序的,同样只需要判断target是否在这个范围内,相应的移动边缘即可。

根据以上方法,每次我们都可以切掉一半的数据,所以算法的时间复杂度是O(logn),空间复杂度是O(1)。代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public int search(int[] A, int target) {  
  2.     if(A==null || A.length==0)  
  3.         return -1;  
  4.     int l = 0;  
  5.     int r = A.length-1;  
  6.     while(l<=r)  
  7.     {  
  8.         int m = (l+r)/2;  
  9.         if(target == A[m])  
  10.             return m;  
  11.         if(A[m]<A[r])  
  12.         {  
  13.             if(target>A[m] && target<=A[r])  
  14.                 l = m+1;  
  15.             else  
  16.                 r = m-1;  
  17.         }  
  18.         else  
  19.         {  
  20.             if(target>=A[l] && target<A[m])  
  21.                 r = m-1;  
  22.             else  
  23.                 l = m+1;                      
  24.         }  
  25.     }  
  26.     return -1;  
  27. }  

例二:

Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

  1. public int searchInsert(int[] A, int target) {  
  2.     if(A == null || A.length == 0)  
  3.     {  
  4.         return 0;  
  5.     }  
  6.     int l = 0;  
  7.     int r = A.length-1;  
  8.     while(l<=r)  
  9.     {  
  10.         int mid = (l+r)/2;  
  11.         if(A[mid]==target)  
  12.             return mid;  
  13.         if(A[mid]<target)  
  14.             l = mid+1;  
  15.         else  
  16.             r = mid-1;  
  17.     }  
  18.     return l;  
  19. }  

例三:

Search a 2D Matrix

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Given target = 3, return true.

因为矩阵是行有序并且列有序,查找只需要先按行查找,定位出在哪一行之后再进行列查找即可,所以就是进行两次二分查找。时间复杂度是O(logm+logn),空间上只需两个辅助变量,因而是O(1),代码如下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public boolean searchMatrix(int[][] matrix, int target) {  
  2.     if(matrix == null || matrix.length==0 || matrix[0].length==0)  
  3.         return false;  
  4.     int l = 0;  
  5.     int r = matrix.length-1;  
  6.     while(l<=r)  
  7.     {  
  8.         int mid = (l+r)/2;  
  9.         if(matrix[mid][0] == target) return true;  
  10.         if(matrix[mid][0] > target)  
  11.         {  
  12.             r = mid-1;  
  13.         }  
  14.         else  
  15.         {  
  16.             l = mid+1;  
  17.         }  
  18.     }  
  19.     int row = r;  
  20.     if(row<0)  
  21.         return false;  
  22.     l = 0;  
  23.     r = matrix[0].length-1;  
  24.     while(l<=r)  
  25.     {  
  26.         int mid = (l+r)/2;  
  27.         if(matrix[row][mid] == target) return true;  
  28.         if(matrix[row][mid] > target)  
  29.         {  
  30.             r = mid-1;  
  31.         }  
  32.         else  
  33.         {  
  34.             l = mid+1;  
  35.         }  
  36.     }     
  37.     return false;  
  38. }  
二分查找是面试中出现频率不低的问题,但是很少直接考二分查找,会考一些变体,除了这道题,还有 Search in Rotated Sorted Array Search for a Range ,思路其实差不多,稍微变化一下即可,有兴趣可以练习一下哈。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值