算法-二分查找1

如何最省内存实现快速查找

二分查找也叫折半查找,是一种针对有序集合的查找算法。

二分查找的思想:在长度为 n 的数组最中查找值等于 m 的元素位置,先用数组中间位置 mid 上的元素与其相比。等于 m 则返回 mid 的值,如果小于 m 则在数组 0 至 mid-1 区间上按照此方法继续比较查找,如果大于 m 则在数组 mid + 1 至 n 区间上按照此方法据需比较查找。

通过上述描述,我们能发现二分查找其实也是运用的递归的方法。递推公式:search(list[low,high]) =serch(list[low,mid - 1]),search(list[mid + 1,high]),终止条件:low > high

二分查找递归代码实现:
	public static int dserch(int[] list,int low,int high,int num){
		if(low > high){
			return -1;
		}
		int mid = (low + high)/2;
		if(list[mid] == num){
			return mid;
		}else if(list[mid] < num){
			return dserch(list,low + 1,high,num);
		}
		else{
			return dserch(list,low + 1,high,num);
		}
	}
二分查找非递归代码实现:
	public static int search(int[] list,int num){
		int low = 0;
		int high = list.length - 1;
		while(low <= high){
			int mid = (high + low)/2;
			if(list[mid] == num){
				return mid;
			}else if(list[mid] > num){
				high = mid - 1;
			}else{
				low = mid + 1;
			}
		}
		return -1;
	}

上述代码中需要注意的几点:

1:循环退出条件:low < high
2:mid 的取值。如果是 mid = (low + high)/2,有可能会值会过大溢出。可以使用下面写法:mid = low + (high - low)/2,如果追求性能优化到极致,可以使用下面写法:mid = low +((high - low)>>1)。相对于除法,计算机运行位运算效率更高。
3:low 和 high 的更新。low = mid + 1,high = mid - 1。

二分查找时间复杂度分析

二分查找每次查找的数据范围都会是上一次的一般,也就是查找数据的范围呈下列趋势:n/2,n/4,n/8…,n/2^k。其中,n 是数组的长度,k是执行次数。最坏的情况,当 n/2^k = 1的时候,也就是数据被查找到k = log2n,所以时间复杂度为:O(logn)。举个例子,当 n 等于 2 的 32 次方的时候,大约 40 亿。反过来,想在 40 亿个数据中找到某个值,大约需要32次比较。

二分查找应用局限性

二分查找依赖的是顺序表结构,即数组。因为二分查找过程中需要不断访问不同区间的中间位置上的元素,只有数组这种结构,随机访问的时间复杂度是 O(1)。如果用链表实现二分查找的话,每次都要遍历不同区间的元素才能确定中间位置上的元素,时间复杂度变得很高了。

二分查找针对的是有序数据。对于频繁插入删除的数据,不建议使用二分查找。因为为了保证数据的有序性,每次使用二分查找之前都需要对数据进行排序,维护成本增加了。

数据量小的时候不适合使用二分法查找。因为遍历一边数组的时间复杂度和二分法查找的时间复杂度相差无几。如果,遍历查找的时候,数据比较的时候耗时过长,此时建议使用二分法查找。减少比较次数,也是在提高算法的执行效率。

如何最省内存实现快速查找

如何在 100 万个整数中查找某个整数?内存限制是 100M,每个数据大小是 8 个字节。
将数据全部获取到内存中,占用大约 80M。然后先对数据排序,再用二分法查找。

总结

本文创作灵感来源于 极客时间 王争老师的《数据结构与算法之美》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。

初入算法学习,必是步履蹒跚,一路磕磕绊绊跌跌撞撞。看不懂别慌,也别忙着总结,先读五遍文章先,无他,唯手熟尔~
与诸君共勉

关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。

算法-二分查找1_第1张图片

你可能感兴趣的:(算法入门)