简单二分查找

时间复杂度

O(logn)

代码实现

简单(序列中不存在重复)二分查找的实现

package main

import "fmt"

// 递归实现
func BinarySearchRecursive(arr []int, item int) int {
	n := len(arr)
	if n < 1 {
		return -1
	}

	return BinarySearchCore(arr, 0, n-1, item)
}

func BinarySearchCore(arr []int, start, end, item int) int {

	if start > end {
		return -1
	}

	mid := (start+end) / 2
	if item < arr[mid] {
		end = mid-1
	} else if item > arr[mid] {
		start = mid+1
	} else {
		return mid
	}

	return BinarySearchCore(arr, start, end, item)
}

// 非递归实现
func BinarySearch(arr []int, item int) int {
	n := len(arr)
	if n < 1 {
		return -1
	}

	start := 0
	end := n-1

	for start <= end {
		mid := (start+end) /2
		if item < arr[mid] {
			end = mid-1
		} else if item > arr[mid] {
			start = mid+1
		} else {
			return mid
		}
	}

	return -1
}

func main() {
	arr := []int{0,1,2,3,4,5,6,7,8,9}
	m := BinarySearchRecursive(arr, 3)
	fmt.Println(m)
	i := BinarySearch(arr, 3)
	fmt.Println(i)
}

代码剖析

  1. for循环条件是 start <= end ,非 start < end 。
  2. mid取值mid := (start+end) / 2,当start和end很大的情况下,相加有可能会发生溢出情况,所以优化为:mid:=start+(end-start)/2 或者更进一步,转化为位运算:mid:=start+((end-start)>>2)。
  3. start和end的更新,注意为mid-1或者mid+1。

场景局限性

  1. 二分查找依赖的是顺序表结构,简单说就是数组。链表不可以,因为链表不支持按下标随机访问。非顺序表结构的数据存储,都比不可以。
  2. 必须是有序的。而且静态数据比较好,频繁的插入,删除,更新的序列,需要频繁维护有序性的序列,不适用。比较适用,一次比较维护有序,多次二分查找的场景。对于频繁更新的序列,可以用堆排序。
  3. 数据量不要太小,数据量太小的话,直接用顺序查找,代替二分,更简单快捷。
  4. 数据量不要太大,因为是顺序表存储结构,数据的存储,需要连续的内存,因为对内存要求“连续”比较苛刻,比如1GB数据,需要1GB连续内存,及时2GB的内存大小,但都是零散内存的,没有1GB的连续内存,用数组存储也无法申请,无法执行。

优点

二分查找除了本身数据占用内存外,计算比较需要的内存开销是很小的,相比二叉树,散列表等,要小的多。

二分查找是最省内存的查找方式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值