二分搜索

计算机科学中,二分搜索英语:binary search),也称折半搜索英语:half-interval search)、对数搜索英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

 

来自 <https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%90%9C%E7%B4%A2%E7%AE%97%E6%B3%95>

 

时间复杂度

折半搜索每次把搜索区域减少一半,时间复杂度为O(log n)。(n代表集合中元素的个数)

空间复杂度

O(1)。虽以递归形式定义,但是尾递归,可改写为循环。

 

来自 <https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%90%9C%E7%B4%A2%E7%AE%97%E6%B3%95>

 

 

实现:Java版本(循环和递归2个版本)

 1 package com.yan.algorithm;
 2 /**
 3  * 二分搜索、折半查找:适用于在有序数组中查找某个值,时间复杂度为O(log n),空间复杂度为O(1)
 4  * @author Yan
 5  *
 6  */
 7 public class BinarySearch {
 8 
 9     public BinarySearch() {
10     }
11 
12     static int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7 };
13 
14     public static void main(String[] args) {
15         BinarySearch bSearch = new BinarySearch();
16         int rs1 = bSearch.binarySearch(arr, 1);
17         int rs2 = bSearch.binarySearch2(arr, 1, 0, arr.length - 1);
18         System.out.println(rs1);
19         System.out.println(rs2);
20     }
21 
22     public int binarySearch(int[] arr, int k) {
23         if (arr == null) {
24             return -1;
25         }
26         int left = 0;
27         int right = arr.length - 1;
28         int mid = (left + right) >> 1;
29         while (left <= right) {
30             if (arr[mid] == k) {
31                 return mid + 1;
32             } else if (k > arr[mid]) {
33                 left = mid + 1;
34             } else {
35                 right = mid - 1;
36             }
37             // 若为 mid=(left+right)/2,会发生溢出。
//问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题。
38              mid = left + ((right - left) >> 1);
39         }
40 
41         return -1;
42     }
43 
44     /**
45      * 递归版本
46      * 
47      * @param arr
48      * @param k
49      * @param left
50      * @param right
51      * @return
52      */
53     public int binarySearch2(int[] arr, int k, int left, int right) {
54         if (left > right) {
55             return -1;
56         }
57         // int mid = (right + left) >> 1;
58         //// 若为 mid=(left+right)/2,会发生溢出。
//问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题。
59         
60         int mid = left + ((right - left) >> 1);
61         if (k > arr[mid]) {
62             // return 函数自身,则每层都会返回底层所返回的值,所以会返回最后找到的那个mid。
63             return binarySearch2(arr, k, mid + 1, right);
64         }
65         if (k < arr[mid]) {
66             return binarySearch2(arr, k, left, mid - 1);
67         }
68         return mid + 1;
69     }
70 }

 

posted on 2016-06-03 19:59  Yanspecial  阅读(222)  评论(0编辑  收藏  举报