二分查找(Java递归版)

折半查找,也称二分查找,在某些情况下相比于线性查找,使用折半查找算法的效率更高。但是该算法的使用的前提是静态查找表中的数据必须是有序的。二分查找较线性查找的时间复杂度更低为O(logn),这也是数组的查找算法中较为高效率的查找算法。

 二分查找的原理:(所查找的数组必须是有序的)

  • 查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;
  • 如果查找元素大于(小于)中间元素,则在数组大于(小于)中间元素的那一半区间中查找,而且跟开始一样从中间元素开始比较。直到在某一步判断时数组为空数组,说明没有找到该元素

二分查找的思路:

先找到有序数组的中间位置mid = (left+right)/2,然后用有序数组找到中间位置的元素,即arr[mid]与目标元素findVal进行比较,若arr[mid]大于findVal,即说明目标元素findVal在arr[mid]的左边,我们就将索引right左移为(mid-1),若arr[mid]小于findVal,即说明目标元素findVal在arr[mid]的右边,我们就将索引left右移为(mid+1),不断的如此折半查找,直到满足条件findVal==arr[mid]为止,说明查找到此元素的索引mid。

代码实现:

public static int binarySearch(int[] arr, int left, int right, int findVal) {

		// 当left > right时,说明递归整个数组,但是没有找到

		if (left > right) {
			return -1;
		}
		int mid = (left + right) / 2;
		int midVal = arr[mid];

		if (findVal > midVal) {// 向右递归
			return binarySearch(arr, mid + 1, right, findVal);
		} else if (findVal < midVal) {
			return binarySearch(arr, left, mid - 1, findVal);// 向左递归
		} else {
			return mid;
		}

	}

经过测试后,可知上诉述的二分查找只能找到目标元素的一个索引,若目标元素在数组有多个,则不能将所有的目标索引找出来。由此我们可以继续对这个二分查找进行完善。

完善思路:

将binarySearch()方法的返回值改为List集合,在else语句中进行对第一次找到的mid,即第一次找到的findval的索引的左右进行顺序查找,若找到则添加到List集合中。下面是博主的实现代码,可供大家参考。若有更好的实现方式,也请大佬们指教。

public static List<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
		// 当 left > right 时,说明递归整个数组,但是没有找到
		if (left > right) {
			return new ArrayList<Integer>();
		}
		int mid = (left + right) / 2;
		int midVal = arr[mid];
		if (findVal > midVal) { // 向 右递归
			return binarySearch2(arr, mid + 1, right, findVal);
		} else if (findVal < midVal) { // 向左递归
			return binarySearch2(arr, left, mid - 1, findVal);
		} else {
			List<Integer> resIndexlist = new ArrayList<Integer>();
			// 向 mid 索引值的左边扫描,将所有满足 findVal, 的元素的下标,加入到集合 ArrayList
			int temp = mid - 1;
			while (true) {
				if (temp < 0 || arr[temp] != findVal) {// 退出

					break;
				}
				// 否则,就 temp 放入到 resIndexlist
				resIndexlist.add(temp);
				temp -= 1; // temp 左移
			}
			resIndexlist.add(mid); //
			// 向 mid 索引值的右边扫描,将所有满足 findVal, 的元素的下标,加入到集合 ArrayList
			temp = mid + 1;
			while (true) {
				if (temp > arr.length - 1 || arr[temp] != findVal) {// 退出
					break;
				}
				// 否则,就 temp 放入到 resIndexlist
				resIndexlist.add(temp);
				temp += 1; // temp 右移
			}
			return resIndexlist;
		}

	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wyyyyyk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值