550 字
3 分钟
LeetCode-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。你必须设计一个时间复杂度为
O(log n)的算法解决此问题。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0输出:4示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3输出:-1示例 3:
输入:nums = [1], target = 0输出:-1
思路
这题的难点我认为是在强调时间复杂度为O(log n),必须用二分查找的情况下,普通数组全局有序不同的是,这里是部分有序
所以我们要在原来的基础上多一个步骤,1. 先判断哪边是有序的,2. 其次才与target比较进行left或right的移动
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 target > nums[mid] && target <= nums[right] { left = mid + 1 } else { right = mid - 1 } } } return -1}时间复杂度为O(nlog n)的解法
虽然这个思路简单,但时间复杂度不论是for还是 sort.Ints(nums)都超了好多
-
for循环遍历数组,时间复杂度是 O(n) -
使用
sort.Ints(nums)排序,时间复杂度是 O(n log n) -
二分查找: 时间复杂度是 O(log n)
func search(nums []int, target int) int { index := 0 for i := 1; i < len(nums); i++ { if nums[i] < nums[i-1] { index = i break } }
sort.Ints(nums) left, right := 0, len(nums)-1 for left <= right { mid := left + (right - left)/2
if nums[mid] == target { return (mid + index)%len(nums) }else if nums[mid] < target { left = mid + 1 }else { right = mid - 1 } } return -1} LeetCode-33. 搜索旋转排序数组
https://sheep44044.github.io/posts/算法/二分查找/leetcode-33-搜索旋转排序数组/