经典算法思想-二分查找

二分查找

概念:

二分查找是一种高效的查找方式,不过要求线性表(注意与非线性表之间的区别,具有四个特征)必须采用顺序存储结构(注意不是链式存储结构),并且元素是有序排列的。

要求:

我们要从一个序列中查找一个元素的时候,二分查找是一种非常快速的查找算法,二分查找又叫折半查找。它对要查找的序列有两个要求,一是该序列必须是有序的(即该序列中的所有元素都是按照大小关系排好序的,升序和降序都可以,本文假设是升序排列的),二是该序列必须是顺序存储的。图1展示的就是一个能进行二分查找的序列。

原理:

  1. 如果待查序列为空,那么就返回-1,并退出算法;这表示查找不到目标元素。

  2. 如果待查序列不为空,则将它的中间元素与要查找的目标元素进行匹配,看它们是否相等。

  3. 如果相等,则返回该中间元素的索引,并退出算法;此时就查找成功了。

  4. 如果不相等,就再比较这两个元素的大小。

  5. 如果该中间元素大于目标元素,那么就将当前序列的前半部分作为新的待查序列;这是因为后半部分的所有元素都大于目标元素,它们全都被排除了。

  6. 如果该中间元素小于目标元素,那么就将当前序列的后半部分作为新的待查序列;这是因为前半部分的所有元素都小于目标元素,它们全都被排除了。

  7. 在新的待查序列上重新开始第1步的工作。

二分查找之所以快速,是因为它在匹配不成功的时候,每次都能排除剩余元素中一半的元素。因此可能包含目标元素的有效范围就收缩得很快,而不像顺序查找那样,每次仅能排除一个元素。

时间复杂度:log(n)

思路:

在这里插入图片描述
1.首先我们看到第一排为一个数组,下面的数字为其下标,数组元素是升序排列的,需要找到的元素是31

2.开始左指针在0下标的位置,右指针在9下标的位置,中间数mid为(0+9)/2=4,下标4位置的元素是27,31>27所以右指针移动到下标7位置(5+9/2=7)上,左指针变为下标5(4+1=5)位置
在这里插入图片描述
3.继续找mid坐标为下标(5+7)/2=6,判断33与31比较,33<31,左指针变为下标5,右指针也变为下标5,判断31=31

4.找到31位置为下标5

Go实现

package main

import "fmt"

func BinarySearch(arr []int, left int, right int, num int)(bool,int){
	// 判断leftIndex是否大于rightIndex
	if left > right {
		return false,-1
	}
	mid := (left + right) / 2
	if (arr)[mid] > num {
		// 说明要找的数,在 left 至 mid-1
		BinarySearch(arr, left, mid-1, num)
	} else if (arr)[mid] < num {
		// 说明要找的数,在 mid+1 至 right
		BinarySearch(arr, mid+1, right, num)
	} else {
		return true,mid
	}
	return false,-1
}

func main() {
	arr := []int{10,14,19,26,27,31,33,35,42,44}
	fmt.Println(BinarySearch(arr, 0, len(arr), 31))
}

PHP实现

<?php
function BinarySearch($arr,$num){
    $left = 0;
    $right = count($arr)-1;
    while($left<=$right){
        $mid = ($left+$right)/2;
        if($arr[$mid]<$num){
            $left = $mid+1;
        }elseif ($arr[$mid]>$num){
            $right = $mid-1;
        }else {
            return true,$mid;
        }
    }
    return false,-1;
}
$arr = array(10,14,19,26,27,31,33,35,42,44);
$a = BinarySearch($arr,31);
var_dump($a);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值