在Go(Golang)中查找排序以及枢轴阵列中枢轴索引的方法

108 阅读2分钟

概述

我们有一个已排序的输入数组,但在某一索引处被枢轴化。例如,考虑以下数组

[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元素,检查midmid+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