Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang二分查找算法

golang二分查找算法实现过程

作者:莫忘初心丶

这段描述概括了Golang中实现二分查找算法的过程,包括基本步骤、时间复杂度及应用场景,文章详细介绍了二分查找的基本原理和代码实现,并提及了其在有序数组查找中的的高效性,并并讨论了进阶应用场景,如适合开发人员和技术爱好者学习和参考

前言

项目中使用到有序数组查找特定元素,简单记录下Golang中二分查找算法。

二分查找算法简介

二分查找算法是一种在有序数组中查找特定元素的高效算法。

它的基本思想是通过不断将查找范围缩小一半,来快速定位目标元素是否存在。该算法要求数组是有序的,这是因为有序数组的特性允许我们在每一步中排除掉一半的元素。

以下是二分查找的基本步骤:

  1. 初始化: 确定数组的初始搜索范围,通常是整个数组。设定lowhigh分别为搜索范围的最低和最高索引。

  2. 中间元素: 计算中间元素的索引,即mid = (low + high) / 2

  3. 比较: 将目标值与中间元素进行比较。

    • 如果目标值等于中间元素,搜索成功,返回中间元素的索引。
    • 如果目标值小于中间元素,说明目标值可能在左半部分,更新high = mid - 1
    • 如果目标值大于中间元素,说明目标值可能在右半部分,更新low = mid + 1
  4. 循环: 重复上述步骤,直到搜索范围缩小到无法再分割,即low > high。此时,如果目标值存在,返回其索引;否则,返回-1表示目标值不存在。

二分查找的时间复杂度是O(log n),其中n是数组的大小。由于每一步都能将搜索范围减半,因此它在大型有序数组中的性能非常高效。这使得二分查找成为一种常用的查找算法。

请注意,二分查找要求数组是有序的,因此在使用之前需要确保数组有序。

二分查找算法简单实现

package main

import "fmt"

// 二分查找函数
func binarySearch(arr []int, target int) int {
	low, high := 0, len(arr)-1

	for low <= high {
		mid := (low + high) / 2

		if arr[mid] == target {
			return mid // 找到目标值,返回索引
		} else if arr[mid] < target {
			low = mid + 1 // 目标值在右半部分,缩小搜索范围
		} else {
			high = mid - 1 // 目标值在左半部分,缩小搜索范围
		}
	}

	return -1 // 目标值不存在
}

func main() {
	// 示例数组,必须是已排序的数组
	arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	// 要查找的目标值
	target := 7

	// 调用二分查找算法
	index := binarySearch(arr, target)

	if index != -1 {
		fmt.Printf("目标值 %d 在数组中的索引是 %d\n", target, index)
	} else {
		fmt.Printf("目标值 %d 不存在于数组中\n", target)
	}
}

在这个例子中,binarySearch函数接受一个已排序的数组和目标值作为参数,然后使用二分查找算法找到目标值的索引。

如果找到目标值,返回其索引;如果找不到,返回-1。

main函数中,我们提供了一个已排序的数组和要查找的目标值,然后调用binarySearch函数进行查找。

二分查找算法进阶使用

二分查找算法在进阶使用时,可以通过一些变体或特殊情况的处理来满足更复杂的需求。

以下是一些二分查找算法的进阶使用场景和技巧:

1. 查找第一个或最后一个等于目标值的元素

在有序数组中,如果存在重复元素,可以通过稍作修改,使二分查找找到第一个等于目标值或最后一个等于目标值的元素。

例如,找到数组中第一个等于目标值的索引:

func firstOccurrence(arr []int, target int) int {
    low, high := 0, len(arr)-1
    result := -1

    for low <= high {
        mid := (low + high) / 2

        if arr[mid] == target {
            result = mid     // 记录当前找到的索引
            high = mid - 1   // 继续在左半部分查找
        } else if arr[mid] < target {
            low = mid + 1    // 目标值在右半部分,缩小搜索范围
        } else {
            high = mid - 1   // 目标值在左半部分,缩小搜索范围
        }
    }

    return result
}

2. 查找第一个大于或等于目标值的元素

如果需要找到数组中第一个大于或等于目标值的元素,可以进行相应的调整:

func firstGreaterOrEqual(arr []int, target int) int {
    low, high := 0, len(arr)-1
    result := -1

    for low <= high {
        mid := (low + high) / 2

        if arr[mid] >= target {
            result = mid     // 记录当前找到的索引
            high = mid - 1   // 继续在左半部分查找
        } else {
            low = mid + 1    // 目标值在右半部分,缩小搜索范围
        }
    }

    return result
}

3. 查找最后一个小于或等于目标值的元素

类似地,如果需要找到数组中最后一个小于或等于目标值的元素:

func lastLessOrEqual(arr []int, target int) int {
    low, high := 0, len(arr)-1
    result := -1

    for low <= high {
        mid := (low + high) / 2

        if arr[mid] <= target {
            result = mid     // 记录当前找到的索引
            low = mid + 1    // 继续在右半部分查找
        } else {
            high = mid - 1   // 目标值在左半部分,缩小搜索范围
        }
    }

    return result
}

4. 查找循环有序数组中的元素

如果数组是循环有序的,可以先找到旋转点,然后分别在两个有序部分中进行二分查找。

这些进阶使用场景展示了如何通过适当的调整,使得二分查找算法适用于更多的情况。在实际应用中,根据具体问题的要求,可以进一步定制二分查找算法的逻辑。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文