概述
我们有一个已排序的输入数组,但在某一索引处被枢轴化。例如,考虑以下数组
[1, 3, 5, 7, 9]
它已经被旋转并在索引3处被枢轴化。
[5, 7, 9, 1, 3]
我们的目的是要找到枢轴的索引。所以上述数组的答案将是3。如果该数组没有被旋转,那么它应该返回-1。例如,对于下面的输入数组,它应该返回-1。
[0, 1, 2, 3, 4]
其他例子
Pivoted Array: [7, 9, 1, 3, 5]
Pivot Index: 2
Pivoted Array: [9, 1, 3, 5, 9]
Pivot Index: 2
Pivoted Array: [1, 3, 5, 7, 9]
Pivot Index: -1
找到枢轴索引的预期时间复杂度是O(logn)。所以我们必须做一个二进制搜索,并做一些修改来找到枢轴索引。
这将是我们的策略
-
做一个二进制搜索。对于每一个mid元素,检查mid或mid+1 是否是支点
-
如果mid的值小于输入数组开始时的值,则在mid的左侧搜索
-
如果mid的值大于输入数组开始的值,则在mid的右边搜索。
以下是相同的程序。
package main
import "fmt"
func main() {
pivot := findPivot([]int{0, 1, 2, 3, 4, 5})
fmt.Println(pivot)
pivot = findPivot([]int{1, 2, 3, 4, 5, 0})
fmt.Println(pivot)
pivot = findPivot([]int{2, 3, 4, 5, 0, 1})
fmt.Println(pivot)
pivot = findPivot([]int{3, 4, 5, 0, 1, 2})
fmt.Println(pivot)
pivot = findPivot([]int{4, 5, 0, 1, 2, 3})
fmt.Println(pivot)
pivot = findPivot([]int{5, 0, 1, 2, 3, 4})
fmt.Println(pivot)
}
func findPivot(nums []int) int {
return findPivotUtil(nums, 0, len(nums)-1)
}
func findPivotUtil(nums []int, start, end int) int {
if start > end {
return -1
}
mid := (start + end) / 2
if mid+1 <= end && nums[mid] > nums[mid+1] {
return mid + 1
}
if mid-1 >= start && nums[mid] < nums[mid-1] {
return mid
}
if nums[mid] < nums[start] {
return findPivotUtil(nums, start, mid-1)
}
return findPivotUtil(nums, mid+1, end)
}
func binarySearch(nums []int, start, end, target int) int {
if start > end {
return -1
}
mid := (start + end) / 2
if nums[mid] == target {
return mid
}
if target < nums[mid] {
return binarySearch(nums, start, mid-1, target)
} else {
return binarySearch(nums, mid+1, end, target)
}
}
输出
-1
5
4
3
2
1