当前位置: 首页 > news >正文

算法基础——二分查找

https://www.geeksforgeeks.org/dsa/binary-search/

文章目录

  • 算法介绍
  • 代码实现
    • 迭代法 ☆☆☆☆☆
      • 1 为什么left <= right 而不是 left < right?
      • 2 为什么有些算法题中出现 left < right?
    • 递归法 ☆☆☆

算法介绍

二分查找算法是一种在已排序数组中,通过将搜索区间反复划分为两半的搜索算法。二分查找的思想是利用数组已排序的信息,将时间复杂度降低到 O(log N)

在这里插入图片描述
有两种方法实现二分查找 (迭代和递归)

代码实现

迭代法 ☆☆☆☆☆

下面这段代码在面试考察时希望可以做到肌肉记忆

 private  int binarySort(int[] nums, int target) {int n = nums.length;int left = 0, right = n - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) return mid;else if (nums[mid] < target) left = mid + 1;else right = mid - 1;}return -1;}

1 为什么left <= right 而不是 left < right?

假设nums数组元素如下,target为 20,预期返回1

index01234
value1020304050
初始值left = 0right = 4
第一次执行left = 0right = 4mid = 0+(4-0)/2 =2nums[mid] > 20, right = mid -1 =1
第二次执行left = 0right = 1mid = 0+(1-0)/2 =0nums[mid] < 20, left = mid +1 =1
第三次执行left = 1right = 1mid = 1+(1-1)/2 =1nums[mid] = 20, 返回1

如上表格所示,如果 left < right就停止比较,那么第三次就不会执行了自然找不到索引为1,而是直接返回 -1,这和预期不符

2 为什么有些算法题中出现 left < right?

  • 如果你要找某个 具体数值的位置:用 low <= high
  • 如果你要找某个 边界 / 极值:用 low < high 更安全(边界不容易越界)

这里我们通过一个题目来加深理解

给定一个非递减排序的数组 nums 和一个目标值 target,返回第一个 大于等于 target 的元素索引。如果不存在,返回 nums.length

int lowerBound(int[] nums, int target) {int low = 0, high = nums.length;  // 注意这里是 high = nums.length,不是 length - 1while (low < high) {int mid = low + (high - low) / 2;if (nums[mid] < target) {low = mid + 1;  // 排除左侧} else {high = mid;     // mid 可能是解,保留它}}return low;
}

递归法 ☆☆☆

private static int binarySort2(int[] nums, int left, int right, int target) {if (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) return mid;else if (nums[mid] < target) return binarySort2(nums, mid + 1, right, target);else return binarySort2(nums, left, mid - 1, target);}return -1;}public static void main(String[] args) {int[] nums = {0, 1, 2, 3, 4, 5};System.out.println(binarySort2(nums, 0, nums.length - 1, 2));}
http://www.lryc.cn/news/605806.html

相关文章:

  • Apache HttpClient HTTP 线程池参数设置
  • Apache RocketMQ 中Message (消息)的核心概念
  • 实现一键将仓库推送到Github和Gitee!!!
  • 每日算法刷题Day56:7.31:leetcode 栈6道题,用时2h30min
  • 【科普】贝叶斯神经网络与分形神经网络
  • 达梦(DM8)常用管理SQL命令(3)
  • Union Application
  • cmake和makefile示例
  • 链表算法题
  • NTLDR源代码分析之从GetSector函数到blread函数
  • vue3.0 + TypeScript 中使用 axios 同时进行二次封装
  • Coze开源版本地部署指南
  • 界面组件DevExpress WPF中文教程:网格视图数据布局 - 数据单元格
  • [源力觉醒 创作者计划]_文心4.5开源测评:国产大模型的技术突破与多维度能力解析
  • nuxt3: trpc-nuxt和sqlite导致的503错误
  • [免费]基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Django+requests库)【论文+源码+SQL脚本】
  • C++11原子操作实现公平自旋锁
  • 如何快速部署主数据管理解决方案?
  • C# XML 文件
  • 深度学习入门:用pytorch跑通GitHub的UNET-ZOO项目
  • mapper.xml中的<include>是什么
  • 摄像头模块的调焦原理
  • uni-app用css编写族谱树家谱树
  • 量子安全:微算法科技(MLGO)基于比特币的非对称共识链算法引领数字经济未来
  • 本地通信的选择:为什么组播比广播更适合多进程协作?
  • NAS、DAS、SAN三种存储介绍
  • [12月考试] E
  • 计算机网络学习--------三次握手与四次挥手
  • 深度学习G5周:Pix2Pix理论与实战
  • docker运行时目录/var/lib/docker 学习