Java算法之入门--二分法

        说个老生常谈的话题:使用二分法的基础是必须有序数组。但是,不妨设想一下,无序数组能不能也用二分法呢?

         针对这个问题,展开下述研究。在谈这个之前,先聊聊什么是二分法

给出一个数组arr = {1,2,3,4,5,6,7}

要求在数组中找到数字6

正常来说,只要遍历一次数组,逐个数字找一遍即可。

但是,如果是二分法,就不一样了。

在目前阶段来说,二分法一定是建立在有序数组基础上的。这句话是有一定道理。

通常,我们会给出 L M R 三个指针,分别代表左部分,中间值,右部分

对于arr数组来说,(1+7)/2 = 4 所以 M = 4 ;

那么明显的 M = 4 < 6 所以左半部分不用看了,直接令L = M

然后更新M = (4个数)/2 = 5 < 6 再次令 L = M 

依次重复,直到找出数字6 

   代码如下:

public static boolean find(int[] arr, int num) {
		if (arr == null || arr.length == 0) {
			return false;
		}
		int L = 0;
		int R = arr.length - 1;
		while (L <= R) {
			int mid = (L + R) / 2;
			if (arr[mid] == num) {
				return true;
			} else if (arr[mid] < num) {
				L = mid + 1;
			} else {
				R = mid - 1;
			}
		}
		return false;
	}

   给个好玩的题目:

                Q:已知arr={1,2,3,4,4,4,5,6,7}在有序数组arr中找到>=4最左的位置

这题直接用二分思想,很快就能解决。代码如下:

public static int mostLeftNoLessNumIndex(int[] arr, int num) {
		if (arr == null || arr.length == 0) {
			return -1;
		}
		int L = 0;
		int R = arr.length - 1;
		int ans = -1;
		while (L <= R) {
			int mid = (L + R) / 2;
			if (arr[mid] >= num) {
				ans = mid;
				R = mid - 1;
			} else {
				L = mid + 1;
			}
		}
		return ans;
	}

 说到这里,二分的思想应该有所了解了。但是有一种情况下,即使数组不是无序的,我们仍然能用二分法,但是这里有一个前提。

       Q: 无序数组,但相邻下标数不相等,能否找到局部最小值,返回一个即可。

局部最小: 3 a 4 ===》a就是局部最小,理解为函数中的极小值

public static int oneMinIndex(int[] arr) {
		if (arr == null || arr.length == 0) {
			return -1;
		}
		int N = arr.length;
		if (N == 1) {
			return 0;
		}
		if (arr[0] < arr[1]) {
			return 0;
		}
		if (arr[N - 1] < arr[N - 2]) {
			return N - 1;
		}
		int L = 0;
		int R = N - 1;
		// L...R 肯定有局部最小
		while (L < R - 1) {
			int mid = (L + R) / 2;
			if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
				return mid;
			} else {
				if (arr[mid] > arr[mid - 1]) {
					R = mid - 1;
				} else {
					L = mid + 1;
				}
			}
		}
		return arr[L] < arr[R] ? L : R;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值