算法:二分法查找

一、概述

二分查找算法 ,是一种在有序数组中查找某一特定元素的搜索算法。 搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。

二、常见算法

1. 有序数组中查找target

public int binarySearch(int[] arr, int target) {
	if (arr == null || arr.length == 0) {
		return -1; //没有找到
	}
	int left = 0;
	int right = arr.length - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] == target) {
			return mid; //找到目标值所在位置
		} else if (arr[mid] > target) {
			right = mid - 1;
		} else {
			left = mid + 1;
		}
	}
	return -1; //没有找到
}

2. 有序数组中查找 >=target 的最左位置

二分法其实可以把数组进行无限二分,最终当数组无法进行二分时,便是退出条件。

public int binarySearch(int[] arr, int target) {
	if (arr == null || arr.length == 0) {
		return -1;
	}
	int left = 0;
	int right = arr.length - 1;
	int ans = -1; //新增一个标记,用于记录>=target的最左元素位置。
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] >= target) {
			ans = mid; //先记录下这个位置,如果mid位置的前一个值<target,则直接返回当前这个mid值。
			right = mid - 1;
			
		} else {
			left = mid + 1;
		}
	}
	return ans;
}

3. 有序数组中查找 <=target 的最右位置

解题方法与在有序数组中查找 >=target 的最左位置类似。

public int binarySearch(int[] arr, int target) {
	if (arr == null || arr.length == 0) {
		return -1;
	}
	int left = 0;
	int right = arr.length - 1;
	int ans = -1; //新增一个标记,用于记录<=target的最右元素位置。
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] <= target) {
			ans = mid; //先记录下这个位置,如果mid位置的前一个值<target,则直接返回当前这个mid值。
			left = mid + 1;
		} else {
			right = mid - 1;
		}
	}
	return ans;
}

4. 局部最小值问题

无数数组arr,一定保证任意位置i和i+1不相等。

  • 左边界:若 arr[0]<arr[1],0位置算是局部最小值。
  • 右边界:若 arr[N-1]<arr[N-2],N-1位置算是局部最小值。
  • 中间部分:若存在 arr[i-1]>arr[i] 且 arr[i]<arr[i+1],则i位置是局部最小值。
    请你找到并返回1个 arr 中的最小值。
public int findMin(int[] arr) {
	if (arr == null || arr.length == 0) {
		return -1;
	}
	int len = arr.length;
	if (len == 1) {//只有一个元素
		return 0;
	}
	if (len == 2) {//两个元素
		return arr[0] < arr[1] ? 0 : 1;
	}
	// 大于两个元素,使用二分法查找。
	int left = 0;
	int right = len - 1;
	// 要预留3个数(left,mid,right)才进入循环。
	while (left <= right - 1) {
		int mid = (left + right) / 2;
		if (arr[mid] < arr[mid-1] && arr[mid] <= arr[mid+1]) {
			return mid;
		} 
		if (arr[mid] > arr[mid-1]) {
			right = mid - 1;
		}
		if (arr[mid] > arr[mid+1]) {
			left = mid + 1;
		}
	}
	// 最终剩2个数的时候,再对比一下。
	return arr[left] < arr[right] ? left : right;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值