数据结构 之 二分法的详解及扩展

本文详细探讨了二分查找法在不同场景下的应用,包括常规查找、查找特定范围的边界位置以及解决局部最小值问题,强调了其在有序数据中的时间复杂度优势。通过实例展示了如何在有序数组中使用二分查找算法,以及如何扩展到无序数组中的局部最小值搜索。
摘要由CSDN通过智能技术生成

二分法又可以被称为二分查找法,它描述了在有序集合中搜索特定值的过程。广义的二分查找是将问题的规模尽可能的缩小到原有的一半。

百度百科的讲解
在这里插入图片描述
其实 二分法 也不一定只适用于 排好序的数据 比如下面的查找局部最小值题目

二分法 时间复杂度为O(logN)

题目一:

从一个有序数组中找到特定的值 如果有则返回true 没则返回false

在这里插入图片描述

public static boolean dichotomy(int[] arrs,int target) {
		//如果数组长度小于1 或 数组为空则返回false
		if(arrs==null | arrs.length<1) {
			return false;
		}
		int mid = arrs.length/2;
		int left=0,right = arrs.length-1;
		while(left<=right) {
			if(arrs[mid] == target) {
				System.out.println(target +"的位置是:"+mid);
				return true;
			}else if(arrs[mid]>target) { //证明目标值在mid的左边
				right = mid-1;
				mid = (left+right)/2;
			}else if(arrs[mid]<target){  //证明目标值在mid的右边
				left = mid+1;
				mid = (left+right)/2;
			}
		}
		//证明找不到目标值
		System.out.println("数组中无此 "+target+" 元素");
		return false;
	}

题目二:

在一个有序数组中 找到>=某个数的最左侧的位置 (此程序一定是二分到结束的)

在这里插入图片描述

public static int dichotomyLeftIndex(int[] arrs,int target) {
		//如果数组长度小于1 或 数组为空 则返回-1 表示找不到
		if(arrs == null | arrs.length <1 ) {
			return -1;
		}
		int mid = arrs.length/2;
		int left = 0,right = arrs.length-1;
		int finalIndex = -1;
		while(left<=right) {
			if(arrs[mid] >= target) { //左侧可能还有答案 继续二分 先记录当前位置
				finalIndex = mid;
				right = mid -1;
				mid = (left+right)/2;
			}else { // 答案在右侧
				left = mid+1;
				mid = (left+right)/2;
			}
		}
		return finalIndex;
	}

题目三:

在一个有序数组中 找到<=某个数的最右侧的位置 (此程序一定是二分到结束的)

在这里插入图片描述

public static int dichotomyRightIndex(int[] arrs,int target) {
			//如果数组长度小于1 或 数组为空 则返回-1 表示找不到
			if(arrs == null | arrs.length <1 ) {
				return -1;
			}
			int mid = arrs.length/2;
			int left = 0,right = arrs.length-1;
			int finalIndex = -1;
			while(left<=right) {
				if(arrs[mid] <= target) { //右侧可能还有答案 继续二分 先记录当前位置
					finalIndex = mid;
					left = mid+1;
					mid = (left+right)/2;
				}else { // 答案在左侧
					right = mid -1;
					mid = (left+right)/2;
				}
			}
			return finalIndex;
		}

题目四:

局部最小值问题:在一个无序数组中 已知相邻两个数一定不相等

在这里插入图片描述

如今要找到这样一个值

如果这个数在最左边 ( 索引为0 ) 且索引为1的值一定大于索引为0的值,这样索引为0的值才能称为局部最小值

如果这个数在最右边 ( 索引为len-1 ) 且索引为 len-2 的值一定大于索引为len-1的值,这样索引为len -1的值才能称为局部最小值

如果这个数在中间 ( 索引为i ) 且索引为 i-1 的值一定大于索引为 i的值,索引为 i+1的值一定大于索引为 i的值,这样索引为i的值才能称为局部最小值

时间复杂度变成O(logN)

public static int searchLocalMin(int[] arrs) {
		//如果数组长度小于1 或 数组为空 则返回-1
		if(arrs == null | arrs.length < 1) {
			return -1;
		}
		//局部最小值 在头部情况 或 数组只有一个数
		if(arrs[0]<arrs[1] || arrs.length==1) {
			return 0;
		}
		//局部最小值 在尾部情况
		if(arrs[arrs.length-1]<arrs[arrs.length-2]) {
			return arrs.length-1;
		}
		int mid = arrs.length/2;
		int left = 1,right = arrs.length-2;
		while(left < right) { 
			System.out.println("mid:"+mid);
			if(arrs[mid]>arrs[mid-1]) { //左侧必有局部最小值
				right = mid - 1;
			}else if(arrs[mid]>arrs[mid+1]) { //右侧必有局部最小值
				left = mid + 1;
			}else {
				//此值就是局部最小值
				return mid;
			}
			 mid = (left+right)/2;
		}
		//这里返回left 是因为while中条件没有等于 如果while条件有等于 这里返回-1
		return left; 
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值