【LeetCode】33. 搜索旋转排序数组

leetcode

 

解题思路

该问题要求在 ​​旋转后的有序数组​​ 中查找目标值,且时间复杂度需为 ​​O(log n)​​。核心思路是 ​​二分查找的变体​​,利用旋转数组的特性:​​数组被分为两个有序子数组​​,通过判断有序区间调整搜索范围。

 

关键步骤:

  1. ​​确定有序区间​​:每次计算中间点 mid,比较 nums[left] 和 nums[mid] 的值,判断左半部分是否有序。
    • 若左半部分有序 (nums[left] <= nums[mid]),检查目标值是否在左半部分的范围内。
    • 若右半部分有序 (nums[left] > nums[mid]),检查目标值是否在右半部分的范围内。
  2. ​​调整搜索范围​​:根据目标值与有序区间的关系,移动左右指针缩小搜索范围。
  3. ​​终止条件​​:找到目标值或左右指针交叉(未找到)。

代码实现

func search(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right {
        mid := left + (right-left)/2 // 防止溢出
        if nums[mid] == target {
            return mid
        }
        // 判断左半部分是否有序
        if nums[left] <= nums[mid] {
            // 检查目标值是否在左半部分的范围内
            if nums[left] <= target && target < nums[mid] {
                right = mid - 1
            } else {
                left = mid + 1
            }
        } else { // 右半部分有序
            // 检查目标值是否在右半部分的范围内
            if nums[mid] < target && target <= nums[right] {
                left = mid + 1
            } else {
                right = mid - 1
            }
        }
    }
    return -1
}

代码注释

  • ​​循环条件​​:left <= right 确保搜索区间有效。
  • ​​中间点计算​​:mid := left + (right-left)/2 避免整数溢出。
  • ​​有序区间判断​​:
    • 若 nums[left] <= nums[mid],左半部分有序。
    • 否则右半部分有序。
  • ​​范围调整​​:根据目标值与有序区间的关系,移动指针。

复杂度分析

  • ​​时间复杂度​​:O(log n),每次二分将搜索范围减半。
  • ​​空间复杂度​​:O(1),仅使用常数级变量。

运行示例

func main() {
    fmt.Println(search([]int{4,5,6,7,0,1,2}, 0)) // 输出 4
    fmt.Println(search([]int{4,5,6,7,0,1,2}, 3)) // 输出 -1
    fmt.Println(search([]int{1}, 0))             // 输出 -1
}

关键点解析

  • ​​有序区间的判定​​:通过 nums[left] 和 nums[mid] 的比较确定哪一部分是有序的。
  • ​​边界条件处理​​:例如 nums[left] <= nums[mid] 中的等号处理,覆盖了左半部分为单元素的情况(如 left == mid)。
  • ​​旋转特性​​:利用旋转后数组的局部有序性,将时间复杂度控制在 O(log n)。
posted @ 2025-04-23 22:31  云隙之间  阅读(61)  评论(0)    收藏  举报