33. 搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。 字节考过。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
- 对于有序数组,可以使用二分查找的方法查找元素。
- 但是这道题中,数组本身不是有序的,进行旋转后只保证了数组的局部是有序的,这还能进行二分查找吗?答案是可以的。
- 其实题目要求还是求某个值在数组中的坐标,但是遍历的方法时间复杂度高,需要利用旋转过的升序数组这个条件来优化时间复杂度。
- 二分的细节是核心。
- 时间复杂度: O(logn),其中 n 为 nums 数组的大小。整个算法时间复杂度即为二分查找的时间复杂度 O(logn)。
空间复杂度: O(1) 。我们只需要常数级别的空间存放变量。
//时间Ologn,空间O1func search(nums []int, target int) int {left, right := 0, len(nums) -1for left <= right {mid := left + (right - left) /2if nums[mid] == target { // 判断正好相等,完事return mid} else if nums[mid] >= nums[left] { // 判断有序在左if nums[mid] > target && target >= nums[left] { // 判断目标值在 有序区间 左边内right = mid - 1} else {left = mid + 1}} else if nums[mid] < nums[left] { // 判断左边不是有序,即有序在右if nums[mid] < target && target <= nums[right] { // 判断目标值在 有序区间 右边内left = mid + 1} else {right = mid -1}}}return -1}

