算法-二分查找

二分查找的前提是:所要查找的数组必须是有序的!
核心算法:

  1. 找到数组的中点下标mid
  2. 如果所要查找的值比mid下标对应的值小,那么要向数组的左半部分进行查找
  3. 如果所要查找的值比mid下标对应的值大,那么要向数组的右半部分进行查找
  4. 如果所要查找的值与mid下标对应的值相同,就返回mid
  5. 若所要查找的数组为空,则返回-1
  6. 递归实现上述过程(也可以用循环代替递归)

算法代码


import java.util.Arrays;

public class BinarySearch {
	private static int[] myArr;

	private BinarySearch() {
	}

	public static BinarySearch instance(int[] arr) {
		myArr = arr;
		return new BinarySearch();
	}

	/**
	 * 
	 * @Title: binarySearch
	 * @Description: 递归实现二分查找
	 * @param: @param
	 *             left 当前所要查找的数组的第一个元素的下标
	 * @param: @param
	 *             right 当前所要查找的数组的最后一个元素的下标
	 * @param: @param
	 *             value 所要查找的值
	 * @return: int 所要查找的值在数组中的下标,若找不到,则返回-1
	 */
	private int binarySearch(int left, int right, int value) {
		// 如果当前数组不为空
		if (left <= right) {
			int mid = (left + right) / 2;// 找到数组的中点下标mid
			// 如果所要查找的值比mid下标对应的值小,那么要向数组的左半部分进行查找
			if (value < myArr[mid]) {
				right = mid - 1;
				return binarySearch(left, right, value);
			} else if (value > myArr[mid]) {// 如果所要查找的值比mid下标对应的值大,那么要向数组的右半部分进行查找
				left = mid + 1;
				return binarySearch(left, right, value);
			} else {// 如果所要查找的值与mid下标对应的值相同,就返回mid
				return mid;
			}
		}

		// 若所要查找的数组为空,则返回-1
		return -1;
	}

	/**
	 * 
	 * @Title: binarySearchs 
	 * @Description: binarySearch的升级版,找出数组中所有符合所查找值的下标 
	 * @param: @param left 
	 * @param: @param right 
	 * @param: @param value 
	 * @return: int[] 存放所有下标的数组,没有找到则返回null
	 */
	private int[] binarySearchs(int left, int right, int value) {
		// 如果当前数组不为空
		if (left <= right) {
			int mid = (left + right) / 2;// 找到数组的中点下标mid
			// 如果所要查找的值比mid下标对应的值小,那么要向数组的左半部分进行查找
			if (value < myArr[mid]) {
				right = mid - 1;
				return binarySearchs(left, right, value);
			} else if (value > myArr[mid]) {// 如果所要查找的值比mid下标对应的值大,那么要向数组的右半部分进行查找
				left = mid + 1;
				return binarySearchs(left, right, value);
			} else {// 如果所要查找的值与mid下标对应的值相同,就查找该下标的左边和右边的元素,把所有与所查找值相同的元素都放到返回数组里

				int[] returnArr = new int[right - left + 1];//创建返回数组
				int k = 0;
				int n = mid - 1;
				
				//查找mid下标的左半部分元素
				while(n >= left && myArr[n] == value) {
					returnArr[k++] = n;
					n--;
				}
				
				returnArr[k++] = mid; //把mid下标放入返回数组
				
				n = mid + 1;
				
				//查找mid下标的右半部分元素
				while(n <= right && myArr[n] == value) {
					returnArr[k++] = n;
					n++;
				}
				
				return Arrays.copyOf(returnArr, k);//返回所有找到的下标构成的数组
			
			}
		}

		// 若所要查找的数组为空,则返回null
		return null;
	}

	/**
	 * 
	 * @Title: binarySearch 
	 * @Description: 二分查找入口 (返回所查找值的第一个下标)
	 * @param: @param value 所要查找的值 
	 * @return: int 查找的值在数组中的下标,没有找到则返回-1 @throws
	 */
	public int binarySearch(int value) {
		return binarySearch(0, myArr.length - 1, value);
	}
	
	/**
	 * 
	 * @Title: binarySearchs 
	 * @Description: 二分查找入口 (返回所查找值对应的多个下标集合)
	 * @param: @param value 所要查找的值 
	 * @return: int 查找的值在数组中的下标,没有找到则返回-1 @throws
	 */
	public int[] binarySearchs(int value) {
		return binarySearchs(0, myArr.length - 1, value);
	}
}

源码:github地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值