如何使用高级二进制搜索?
为什么以及如何?
当我在 leetcode 上解决问题时,它说在给定的按非递减顺序排序的整数数组 nums 中,找到给定目标值的开始和结束位置。因此不可能用简单的二进制 Sarch 来返回数组中目标元素的开始和结束,因为它只返回找到第一个目标元素的索引,该元素可以是该元素的第一个、结尾或中间的任何内容。所以我们使用 Double Binary Scarch ,具体方法如下...
方法
-
第一次二分查找:
- 执行二分搜索以查找目标的最后一次出现。
- 以 si(起始索引)从 0 开始,以 ei(结束索引)从 nums.length - 1 开始。
- 如果中间元素nums[mid]小于目标,则将起始索引si移动到mid + 1以在右半部分搜索。
- 如果大于目标,则将结束索引ei移动到mid - 1以在左半部分搜索。
- 如果 nums[mid] 等于目标,则将 res[1] 设置为 mid(范围的当前末尾),并继续在右半部分 (si = mid + 1) 中搜索以找到最后一次出现的位置。
-
第二次二分查找:
- 执行另一次二分搜索以查找目标的第一次出现。
- 将 si 重置为 0,将 ei 重置为 nums.length - 1。
- 遵循与之前类似的方法,但如果 nums[mid] 等于目标,则将 res[0] 设置为 mid(范围的当前开始)并继续在左半部分搜索 (ei = mid - 1)找到第一个出现的位置。
-
返回结果:
- 结果数组 res 包含目标值的起始和结束索引。
复杂
-
时间复杂度:
- 二分查找第一次和最后一次出现的时间分别需要 O(log n) 时间。由于我们执行两次二分搜索,因此总体时间复杂度为 O(log n)。
-
空间复杂度:
- O(1),因为我们为变量使用固定量的额外空间。
代码
class Solution { public int[] searchRange(int[] nums, int target) { int ei = nums.length - 1; int si = 0; int[] res = {-1, -1}; // Initialize result array // First binary search to find the last occurrence while (si <= ei) { int mid = si + (ei - si) / 2; if (target < nums[mid]) { ei = mid - 1; } else if (target > nums[mid]) { si = mid + 1; } else { res[1] = mid; // Update end index si = mid + 1; // Search in the right half } } // Reset the pointers for the second binary search si = 0; ei = nums.length - 1; // Second binary search to find the first occurrence while (si <= ei) { int mid = si + (ei - si) / 2; if (target < nums[mid]) { ei = mid - 1; } else if (target > nums[mid]) { si = mid + 1; } else { res[0] = mid; // Update start index ei = mid - 1; // Search in the left half } } return res; // Return the result array } }
以上是如何使用高级二进制搜索?的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undress AI Tool
免费脱衣服图片

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

HashMap在Java中通过哈希表实现键值对存储,其核心在于快速定位数据位置。1.首先使用键的hashCode()方法生成哈希值,并通过位运算转换为数组索引;2.不同对象可能产生相同哈希值,导致冲突,此时以链表形式挂载节点,JDK8后链表过长(默认长度8)则转为红黑树提升效率;3.使用自定义类作键时必须重写equals()和hashCode()方法;4.HashMap动态扩容,当元素数超过容量乘以负载因子(默认0.75)时,扩容并重新哈希;5.HashMap非线程安全,多线程下应使用Concu

tosetjava_homeonwindows,firstLocateThejDkinStallationPath(例如,C:\ programFiles \ java \ jdk-17),tencreateasyemystemenvironmentvaria blenamedjava_homewiththatpath.next,updateThepathvariaby byadding%java \ _home%\ bin,andverifyTheSetupusingjava-versionAndjavac-v

虚拟线程在高并发、IO密集型场景下性能优势显着,但需注意测试方法与适用场景。 1.正确测试应模拟真实业务尤其是IO阻塞场景,使用JMH或Gatling等工具对比平台线程;2.吞吐量差距明显,在10万并发请求下可高出几倍至十几倍,因其更轻量、调度高效;3.测试中需避免盲目追求高并发数,适配非阻塞IO模型,并关注延迟、GC等监控指标;4.实际应用中适用于Web后端、异步任务处理及大量并发IO场景,而CPU密集型任务仍适合平台线程或ForkJoinPool。

要正确处理JDBC事务,必须先关闭自动提交模式,再执行多个操作,最后根据结果提交或回滚;1.调用conn.setAutoCommit(false)以开始事务;2.执行多个SQL操作,如INSERT和UPDATE;3.若所有操作成功则调用conn.commit(),若发生异常则调用conn.rollback()确保数据一致性;同时应使用try-with-resources管理资源,妥善处理异常并关闭连接,避免连接泄漏;此外建议使用连接池、设置保存点实现部分回滚,并保持事务尽可能短以提升性能。

实现链表的关键在于定义节点类并实现基本操作。①首先创建Node类,包含数据和指向下一个节点的引用;②接着创建LinkedList类,实现插入、删除和打印功能;③append方法用于在尾部添加节点;④printList方法用于输出链表内容;⑤deleteWithValue方法用于删除指定值的节点,处理头节点和中间节点的不同情况。

ServiceMesh是Java微服务架构演进的必然选择,其核心在于解耦网络逻辑与业务代码。1.ServiceMesh通过Sidecar代理处理负载均衡、熔断、监控等功能,使开发聚焦业务;2.Istio Envoy适合中大型项目,Linkerd更轻量适合小规模试水;3.Java微服务应关闭Feign、Ribbon等组件,交由Istiod管理服务发现与通信;4.部署时确保Sidecar自动注入,注意流量规则配置、协议兼容性、日志追踪体系建设,并采用渐进式迁移和前置化监控规划。

创建并使用SimpleDateFormat需要传入格式字符串,如newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");2.注意大小写敏感、避免混用单字母格式及YYYY和DD的误用;3.SimpleDateFormat不是线程安全的,多线程环境下应每次新建实例或使用ThreadLocal;4.使用parse方法解析字符串时需捕获ParseException,并注意结果不带时区信息;5.Java8及以上推荐使用DateTimeFormatter和Lo

为提升Java集合框架性能,可从以下四点优化:1.根据场景选择合适类型,如频繁随机访问用ArrayList、快速查找用HashSet、并发环境用ConcurrentHashMap;2.初始化时合理设置容量和负载因子以减少扩容开销,但避免内存浪费;3.使用不可变集合(如List.of())提高安全性与性能,适用于常量或只读数据;4.防止内存泄漏,使用弱引用或专业缓存库管理长期存活的集合。这些细节显着影响程序稳定性与效率。
