ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LeetCode-Go 题解:33. Search in Rotated Sorted Array 旋转数组二分查找实现解析

LeetCode-Go 题解:33. Search in Rotated Sorted Array 旋转数组二分查找实现解析 LeetCode-Go 题解33. Search in Rotated Sorted Array 旋转数组二分查找实现解析【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go导读本文以 LeetCode-Go 仓库中第 33 题「Search in Rotated Sorted Array」的题解文档为主线深入讲解升序数组在未知枢轴处旋转后如何用 O(log n) 二分查找定位目标值这一经典算法问题。你将掌握旋转数组的二分区间判定技巧、无重复与有重复两种场景的实现差异并通过仓库内真实源码与测试用例验证算法正确性最终能够独立实现并测试此类题目。题目背景与核心要求原题33. Search in Rotated Sorted Array的完整描述如下Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.(i.e.,[0,1,2,4,5,6,7]might become[4,5,6,7,0,1,2]).You are given a target value to search. If found in the array return its index, otherwise return-1.You may assume no duplicate exists in the array.Your algorithms runtime complexity must be in the order ofO(logn).示例 1Input: nums [4,5,6,7,0,1,2], target 0 Output: 4示例 2Input: nums [4,5,6,7,0,1,2], target 3 Output: -1提炼出的关键约束有三点原数组升序排列且在某个未知枢轴处旋转数组中不存在重复元素算法时间复杂度必须为O(log n)级别。正是因为第 3 点约束线性扫描O(n)不可接受必须借助数组整体基本有序的特性设计二分搜索。解题思路对断开点二分旋转数组的结构特征数组原本从小到大排列现在把末尾随机一段有序序列搬到数组前面从而形成前后两段各自升序的子序列。例如[0,1,2,4,5,6,7]旋转为[4,5,6,7,0,1,2]后前段[4,5,6,7]数值相对较大后段[0,1,2]数值相对较小两段之间有一个断开点即 7 与 0 的衔接处。虽然中间存在这个断开点但每一段内部依然单调有序这正是二分搜索能够继续发挥作用的前提。区间归属判定比较 nums[mid] 与两端点设low、high、mid分别为左边界、右边界与中点通过对nums[mid]与nums[low]、nums[high]的大小比较可以判断mid落在哪一段若nums[mid] nums[low]说明mid落在数值较大的前段若nums[mid] nums[low]说明mid落在数值较小的后段若nums[mid] nums[high]说明mid落在数值较小的后段若nums[mid] nums[high]说明mid落在数值较大的前段。另外还存在nums[low] nums[mid]与nums[high] nums[mid]两个边界情形需单独处理仓库实现中以low/high--的方式逐步收缩边界。收缩区间的决策逻辑以 mid 所在段的单调性为基础再结合 target 与段端点的比较决定向哪一侧收缩mid 位于数值较大的前段时前段[low..mid]严格单调递增。若nums[low] target nums[mid]则 target 只可能落在[low, mid-1]令high mid - 1否则令low mid 1mid 位于数值较小的后段时后段[mid..high]严格单调递增。若nums[mid] target nums[high]则 target 只可能落在[mid1, high]令low mid 1否则令high mid - 1循环中若nums[mid] target直接返回mid循环结束仍未命中返回-1。由于每一轮都能把搜索区间压缩约一半整体时间复杂度为 O(log n)。仓库源码实现详解题解文档中的核心代码如下对应仓库文件 leetcode/0033.Search-in-Rotated-Sorted-Array/33. Search in Rotated Sorted Array.gopackage leetcode func search33(nums []int, target int) int { if len(nums) 0 { return -1 } low, high : 0, len(nums)-1 for low high { mid : low (high-low)1 if nums[mid] target { return mid } else if nums[mid] nums[low] { // 在数值大的一部分区间里 if nums[low] target target nums[mid] { high mid - 1 } else { low mid 1 } } else if nums[mid] nums[high] { // 在数值小的一部分区间里 if nums[mid] target target nums[high] { low mid 1 } else { high mid - 1 } } else { if nums[low] nums[mid] { low } if nums[high] nums[mid] { high-- } } } return -1 }对实现细节的逐一说明空数组守卫函数入口处先判断len(nums) 0直接返回-1避免对空切片执行下标访问中点计算使用mid : low (high-low)1而非(lowhigh)/2既防止整型溢出又通过右移一位完成除以 2 的运算循环条件for low high保证区间为空时退出此时未找到 target返回-1区间归属判断的先后顺序先判nums[mid] nums[low]大值段再判nums[mid] nums[high]小值段最后落入else处理nums[low] nums[mid]或nums[high] nums[mid]的退化情形边界处理else分支中通过low、high--各推进一步逐步排除与nums[mid]相等的端点。这一防御性写法使得本实现即使在含有重复元素的数组上运行也具备一定容错能力严格场景对应第 81 题。从函数命名可见search33中的33是题目编号遵循仓库题号题目名的组织约定与其它题解如search81相互独立、互不干扰。测试用例与验证仓库为本题提供了完整的表驱动测试见 leetcode/0033.Search-in-Rotated-Sorted-Array/33. Search in Rotated Sorted Array_test.go。测试覆盖了以下典型场景输入 numstarget期望输出覆盖场景[3, 1]11长度为 2、旋转点在中间的最小规模用例[4,5,6,7,0,1,2]04题目给出的标准示例[4,5,6,7,0,1,2]3-1目标值不存在返回 -1[5,6,7,0,1,2,3,4]25target 位于后段小值段[5,6,7,0,1,2,3,4]61target 位于前段大值段[1,1,1,1,1,1,1]2-1全等元素触发边界推进分支[]5-1空数组守卫测试框架使用question33/para33/ans33三个结构体组织用例para33封装nums与target两个输入参数ans33记录期望索引Test_Problem33遍历全部用例调用search33(p.nums, p.target)并与期望值比对不一致时通过t.Fatalf立即失败。运行方式遵循仓库根目录 gotest.sh 中定义的测试命令go test -covermodeatomic -coverprofilecoverage.txt ./leetcode/...该命令一次性对leetcode/...下所有包执行带覆盖率统计的测试其中就包含本题所在包项目覆盖率为 100% 的目标也正是通过此类完备用例来保障的。延伸与第 81 题含重复元素的关系本题的进阶版本是 81. Search in Rotated Sorted Array II区别仅在于数组可能包含重复元素返回值从索引变为布尔值存在返回true否则返回false。仓库该题 README 明确指出这一题是第 33 题的加强版实现代码完全一样只不过输出变了——即nums[low] nums[mid]、nums[high] nums[mid]时的low/high--收缩策略正是为应对重复元素而保留的防御性逻辑。需要指出的是一旦引入重复元素最坏情况下例如数组全为同一元素二分退化到线性扫描时间复杂度上升为 O(n)而第 33 题在无重复的前提下各分支都保证收缩一半区间始终严格保持 O(log n)。总结本题是有序数组 旋转类二分问题的经典范式核心方法论可以沉淀为三步识别结构旋转数组由两段单调区间组成单调性是二分的前提定位区间通过nums[mid]与nums[low]、nums[high]的关系判断 mid 处于大值段还是小值段定向收缩依据所在段的单调性用 target 与段端点的比较决定搜索方向逐轮减半区间。掌握这一思路后可顺势完成第 81 题含重复元素、第 153/154 题寻找旋转数组最小值等一系列同族题目它们共享同一套区间判定框架。【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表