Go语言算法学习,从二分查找法开始最合适不过了

简介: Go语言算法学习,从二分查找法开始最合适不过了

/ Go 语言实现二分查找算法 /

二分查找是一种高效的搜索算法,它可以在有序数据中快速查找目标值。本文将详细介绍如何使用 Go 语言实现二分查找,代码示例附带详细注释说明。

主要内容包括:

  1. 算法介绍
  2. 最简实现
  3. 递归实现
  4. 迭代实现
  5. 查找第一个值
  6. 查找最后一个值
  7. 处理重复值
  8. 边界条件
  9. 泛型实现
  10. 测试用例

希望通过具体的代码实例,可以帮助大家更好地理解二分查找原理,并练习 Go 语言算法编码能力。实现一个经典算法也有利于提高编程思维能力。

1

 

1. 算法介绍

二分查找针对有序数据设计,可以快速定位目标值。基本思路是:

  1. 从中间元素开始查找
  2. 如果中间元素正好是目标值,返回索引
  3. 如果目标值大于或者小于中间元素,在一半区间重复查找

复杂度为 O(logN)。

2

 

2. 最简实现

首先,一个最简单的实现是:

func binarySearch(nums []int, target int) int {
  low, high := 0, len(nums)-1
  for low <= high {
    mid := low + (high-low)/2
    if nums[mid] == target {
      return mid 
    } else if nums[mid] < target {
      low = mid + 1
    } else {
      high = mid - 1
    }
  }
  return -1   
}

这实现了二分查找的基本逻辑。

3

 

3. 递归实现

递归实现二分查找:

func recursiveSearch(nums []int, low, high, target) int {
  if low > high { // 退出条件
    return -1
  }
  mid := low + (high-low)/2
  if nums[mid] == target {
    return mid
  } else if nums[mid] < target {
    return recursiveSearch(nums, mid+1, high, target) 
  } else {
    return recursiveSearch(nums, low, mid-1, target)
  }
}

递归实现二分查找关键是退出条件与递归调用。

4

 

4. 迭代实现

我们也可以用迭代实现二分查找:

func iterativeSearch(nums []int, target) int {
  low, high := 0, len(nums)-1
  for low <= high {
    mid := low + (high-low)/2
    if nums[mid] == target {
      return mid
    } else if nums[mid] < target {
      low = mid + 1
    } else {
      high = mid - 1 
    }
  }
  return -1
}

迭代实现通常更高效,但是递归实现可以训练思维。

5

 

5. 查找第一个值

要查找第一个等于目标值的元素:

func searchFirstOf(nums []int, target int) int {
  low, high := 0, len(nums) - 1
  for low <= high {
    mid := low + (high-low)/2
    if nums[mid] > target {
      high = mid - 1
    } else if nums[mid] < target {
      low = mid + 1 
    } else {
      if mid == 0 || nums[mid-1] != target {
        return mid
      }
      high = mid - 1  
    }
  }
  return -1
}

这样可以查找到目标值在数组中第一次出现的位置。

6

 

6. 查找最后一个值

查找最后一个等于目标值的元素:

func searchLastOf(nums []int, target int) int {
  low, high := 0, len(nums) - 1
  for low <= high {
    mid := low + (high-low)/2
    if nums[mid] > target {
      high = mid - 1
    } else if nums[mid] < target {
      low = mid + 1
    } else {
      if mid == len(nums)-1 || nums[mid+1] != target {
        return mid 
      }
      low = mid + 1 
    }
  }
  return -1 
}

这通过调整查找范围可以查找到目标值最后一次出现的位置。

7

 

7. 处理重复值

对含重复值的数组二分查找也是可以的:

func searchDup(nums []int, target int) bool {
  low, high := 0, len(nums) - 1
  for low <= high {
    mid := low + (high-low)/2
    if nums[mid] == target {
      return true 
    }
    // 跳过重复值
    for low < mid && nums[low] == nums[mid] { 
      low++
    }
    for high > mid && nums[high] == nums[mid] {
      high--
    }
    if nums[mid] > target {
      high = mid - 1
    } else {
      low = mid + 1
    }
  }
  return false
}

这里使用了一种跳过重复元素的方法。

8

 

8. 边界条件

需要注意二分查找的边界条件:

  • 最小索引最小为 0
  • 最大索引最大为 len(nums) - 1
  • 循环退出条件 low > high
  • 初始化 low 和 high

这样可以避免数组越界问题。

9

 

9. 泛型实现

可以使用泛型实现通用的二分查找:

func BinarySearch[T comparable](nums []T, target T) int {
  low, high := 0, len(nums) - 1
  for low <= high {
    mid := low + (high-low)/2
    switch {
      case nums[mid] < target:
        low = mid + 1
      case nums[mid] > target:
        high = mid - 1
      default:
        return mid  
    }
  }
  return -1 
}

这样可以支持所有可比较类型。

10

 

10. 测试用例

编写测试用例验证二分查找算法非常必要:

func TestBinarySearch(t *testing.T) {
  nums := []int{1, 2, 3, 4}
  if BinarySearch(nums, 2) != 1 {
    t.Error("2应该在索引1处:") 
  }
  if BinarySearch(nums, 6) != -1 { 
    t.Error("未找到 6 应返回 -1:")
  }
}

一定要测试边界条件。

11

 

总结

至此我们使用 Go 语言实现了二分查找算法,并学习了递归和迭代两种实现方式,重点理解算法思想和编程技巧,可以继续扩展改进算法。


目录
相关文章
|
9月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
285 2
|
10月前
|
安全 Java 编译器
对比Java学习Go——基础理论篇
本章介绍了Java开发者学习Go语言的必要性。Go语言以简单、高效、并发为核心设计哲学,摒弃了传统的类继承和异常机制,采用组合、接口和多返回值错误处理,提升了代码清晰度与开发效率。Go直接编译为静态二进制文件,启动迅速、部署简便,其基于Goroutine和Channel的并发模型相较Java的线程与锁机制更轻量安全。此外,Go Modules简化了依赖管理,与Java的Maven/Gradle形成鲜明对比,提升了构建与部署效率。
640 1
|
11月前
|
机器学习/深度学习 算法 数据挖掘
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
306 0
|
9月前
|
存储 监控 算法
基于 Go 语言跳表结构的局域网控制桌面软件进程管理算法研究
针对企业局域网控制桌面软件对海量进程实时监控的需求,本文提出基于跳表的高效管理方案。通过多级索引实现O(log n)的查询、插入与删除性能,结合Go语言实现并发安全的跳表结构,显著提升进程状态处理效率,适用于千级进程的毫秒级响应场景。
336 15
|
10月前
|
存储 算法 搜索推荐
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
专攻软考高频算法,深度解析二分查找、堆排序、快速排序核心技巧,对比九大排序算法,配套动画与真题,7天掌握45%分值模块。
420 1
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
|
9月前
|
存储 缓存 算法
如何管理员工上网:基于 Go 语言实现的布隆过滤器访问拦截算法应用
布隆过滤器以空间换时间,通过多哈希函数实现黑名单的高效存储与毫秒级检索,解决传统方案内存占用大、响应慢等问题,助力企业低成本、高效率管理员工上网行为。
362 3
|
9月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
440 2
|
10月前
|
存储 监控 算法
企业电脑监控系统中基于 Go 语言的跳表结构设备数据索引算法研究
本文介绍基于Go语言的跳表算法在企业电脑监控系统中的应用,通过多层索引结构将数据查询、插入、删除操作优化至O(log n),显著提升海量设备数据管理效率,解决传统链表查询延迟问题,实现高效设备状态定位与异常筛选。
233 3
|
10月前
|
机器学习/深度学习 运维 算法
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
387 1
|
10月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
291 4

热门文章

最新文章