在 算法系列(一)基本概念 一文中,简单介绍了算法基本概念,算法复杂度评估,常用算法证明方式。这篇文章介绍一下查找算法,主要是二分查找算法。
从n个元素中A0,A1....An-1中,找到要找到的元素x,最简单的方法是遍历n个元素,找到元素x则返回x的位置,这种算法的时间复杂度为O(n)。
如果这n个元素是有序的,我们不需要从头到尾遍历一遍就可以找到要查找的元素,可以使用二分法。二分查找的时间复杂度是O(lgn)
二分查找的前提是元素有序(一般是升序),基本思想是拿中间元素A[m]与要查找的元素x进行比较,如果相等,则已经找到,如果A[m]比x大,那么要找的元素一定在A[m]前边,如果A[m]比x小,那么要找的元素一定在A[m]后边。没进行一次查找,数组规模减半。反复将子数组规模减半,直到发现要查找的元素,或者当前子数组为空。
例如,在[1,2,3,4,5]中查找2
第一次找到的数字下标是(0+4)/2=2,找到的数字是3,3<2,要找的数字位置位于[0,2)之间
第二次找到的数字下标是(0+1)/2=0,找到的数字是1,1<2,要找的数字位于(0,1]之间
第三次找到的数字下标是(1+1)/2=1,找到数字2,返回找到的位置1.
如果这个时候找到的数字不是1,那么说明数组中没有要找的数字。
需要注意的点就是区间位置,既然A[m]不等于x,下一次肯定不是从m这个位置开始找的,而是以m+1作为下一个起始位置,或者m-1作为下一个开始位置
二分查找有两种实现方式,一种是递归实现,一种是非递归实现
直接上代码
package com.algorithm.tree; import java.util.Arrays; /** * 二分查找 * * @author chao * */ public class BinarySearchTree { /** * 非递归二分查找 * * @param num * @param number * @return */ public static int binarySearch(int num[], int number) { if (num == null || num.length == 0) { return -1; } int start, end, mid; start = 0; end = num.length - 1; while (start <= end) { mid = (start + end) / 2; if (num[mid] == number) return mid; else if (num[mid] > number) { end = mid - 1; } else { start = mid + 1; } } return -1; } /** * 递归查找 * * @param num * @param number * @return */ public static int RecursivebinarySearch(int num[], int start, int end, int key) { int mid = (start + end) / 2; if (num == null || num.length == 0 || key < num[start] || key > num[end]) { return -1; } else if (num[mid] > key) { return RecursivebinarySearch(num, start, mid - 1, key); } else if (num[mid] < key) { return RecursivebinarySearch(num, mid + 1, end, key); } else { return mid; } } public static void main(String[] args) { int num[] = { 3, 5, 7, 9, 10 }; Arrays.sort(num); System.out.println(binarySearch(num, 7)); System.out.println(binarySearch(num, 8)); System.out.println(RecursivebinarySearch(num, 0, num.length - 1, 7)); System.out.println(RecursivebinarySearch(num, 0, num.length - 1, 8)); } }
算法实现代码github地址为https://github.com/robertjc/simplealgorithm
后续会不断补充,有些地方写的可能有问题,请多指教。
欢迎扫描二维码,关注我的公众账号