二分查找 vs. N分查找

二分查找

  二分查找(Binary Search)又称折半查找,是一种高效率的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

二分查找原理

  满足表中元素有序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成两个子表,根据中间关键字和查找关键字的关系在子表中查找,重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

二分查找分析

  优点: 比较次数少,查找速度快,平均性能好。
  缺点: 要求待查表为有序表,且插入删除困难。
  适用范围: 不经常变动而查找频繁的有序列表。
  时间复杂度: O( log ⁡ 2 N \log_2 N log2N)

代码实现

// C++
int binarySearch(vector<int>& nums, int target) {
	int mid;  // 中间位置 
	int left = 0;  // 左边界 
	int right = nums.size() - 1;  // 右边界 
	
	while (left <= right) { // 折半查找 
		mid = left + (right - left) / 2;  // 计算中间位置 
		
		if (nums[mid] == target) {  // 与中间位置元素比较 
			return mid;  // 查找成功,返回位置信息 
		} else if (target < nums[mid]) {  // 小于中间位置元素 
			right = mid - 1;  // 改变右边界  
		} else {  // 大于中间位置元素 
			left = mid + 1;  // 改变左边界 
		}
	}
	
	return -1;  // 查找失败返回-1 
}

三分查找

三分查找原理

  三分查找,类似于二分查找,区别在于利用两个中间位置记录,将表分为三个子表。

三分查找分析

  时间复杂度: O( log ⁡ 3 N \log_3 N log3N)

代码实现

// C++
int trisectionSearch(vector<int>& nums, int target) {
    int midl;  // 靠左中间位置 
    int midr;  // 靠右中间位置
    int left = 0;  // 左边界
	int right = nums.size() - 1;  // 右边界 
	
    while (left <= right) {  // 三分查找 
    	midl = left + (right - left) / 3;  // 计算靠左中间位置
    	midr = right - (right - left) / 3;  // 计算靠右中间位置
    	
    	if (target < nums[midl]) {  // 小于靠左中间位置
			right = midl - 1;  // 改变右边界 
		} else if (target > nums[midr]) {  // 大于靠右中间位置  
			left = midr + 1;  // 改变左边界
		} else if (target != nums[midl] && target != nums[midr]) {  // 不等于左右中间位置
			left = midl + 1;  // 改变左边界
			right = midr - 1;  // 改变右边界 
		} else {  // 等于左或右中间位置 
			return nums[midl] == target ? midl : midr;  // 查找成功,返回位置信息 
		}
	}
	
    return -1;  // 查找失败返回-1
}

算法分析

由时间复杂度看,三分查找是不是优于二分查找呢?
  二分查找每次查询范围减少一半,需要查询的次数是 log ⁡ 2 N \log_2 N log2N。三分查找每次查询两个数字与目标数字比较,可以把查询范围缩小成原先的 1 / 3。查询次数就只有 log ⁡ 3 N \log_3 N log3N,一下子就优化了这么多,那如果是四分,五分,六分,七分,N分岂不是能无限优化。

  答案并非如此,因为二分法和三分法的渐进复杂度是一样的。

A

   log ⁡ 2 3 \log_2 3 log23是个常数,因此,两个函数是同阶无穷大。任意两个对数函数 log ⁡ a N \log_a N logaN log ⁡ b N \log_b N logbN,比较它们的无穷大阶数都会得到 log ⁡ a b \log_a b logab,是个常数。因此对数函数的底对于算法的复杂度分析是没有意义的。
  因此,无论是二分法,三分法,四分法,N分法······复杂度都是一样的,分的越多,代码反而越复杂,得不偿失。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值