题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2] )
。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -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
代码实现
//1. 先二分遍历找到分隔点index,特征是 < 前一个元素, >后一个元素;
//2. 把数组分成二个部分,[0,index-1], [index,length-1];
//3. 分别使用二分查找,找到给定的值。
//时间复杂度为log(n). 不确定有什么更好的办法
func search(nums []int, target int) int {
if len(nums) == 0 {
return -1
}
n := len(nums) - 1
divisionIndex := findDivision(nums)
if divisionIndex == 0 || divisionIndex == -1 {
//非旋转排序数组
return findTarget(nums, 0, n, target)
}
res := findTarget(nums, 0, divisionIndex-1, target)
if res != -1 {
return res
}
return findTarget(nums, divisionIndex, n, target)
}
//找到分割点
func findDivision(nums []int) int {
low, high := 0, len(nums)-1
for low < high {
mid := low + (high-low)>>1
if nums[high] < nums[mid] {
low = mid + 1
} else {
high = mid
}
}
return low
}
func findTarget(nums []int, low, high, target int) int {
for low <= high {
mid := low + (high-low)>>1
if nums[mid] > target {
high = mid - 1
} else if nums[mid] < target {
low = mid + 1
} else {
return mid
}
}
return -1
}
思路
- 先二分遍历找到分隔点index,特征是 < 前一个元素, >后一个元素;
- 把数组分成二个部分,[0,index-1], [index,length-1];
- 分别使用二分查找,找到给定的值。
GitHub
- 源码传送门
- 各种数据结构及算法实现, LeetCode解题思路及答案
- 大厂面试题汇总及答案解析
参考资料
本文为原创文章,转载注明出处,欢迎扫码关注公众号 楼兰
或者网站https://lovecoding.club,第一时间看后续精彩文章,觉得好的话,顺手分享到朋友圈吧,感谢支持。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。