Go语言数据结构和算法(二十九)斐波那契搜索

17 阅读3分钟

斐波那契搜索是一种基于比较的算法.它使用斐波那契数列来搜索有序数组中的元素.斐波那契算法是基于分治算法的二分搜索算法的另一种变体.

1.原理:

1.1定义两个变量.Fm和Fm-1.其中Fm是第m个斐波那契数.m-1是第m-1个.令m为Fm大于或等于数组长度的最小整数.

1.2将offset和index两个变量初始化为0.并将mid设置为min(offset+Fm-1,n-1).

1.3如果mid索引处的元素等于查找元素.则返回mid.

1.4如果查找元素小于mid索引处元素.则丢弃mid+1~n-1的元素.将Fm-2设置为Fm-1.将Fm-1设置为Fm-Fm-2.将mid设置为min(offset+Fm-2,n-1).

1.5重复步骤3-5直到找到元素或数组末尾.

2.使用场景:

优化:

斐波那契算法可用于在给定区间内找到函数的最优值..可用于优化产品设计或为机器学习模型寻找最佳参数.

数据分析:

斐波那契搜索算法可用于在大型数据集中搜索特定数据点.当数据按待定顺序排序时.效果最明显.

机器学习:

斐波那契搜索算法可用于优化机器学习模型的超参数.可以帮助提高模型的性能并减少过度拟合.

3.实现:

3.1方法:

package data

func FibonacciSearch(array []int) []int {
	if len(array) < 2 {
		return array
	}
	//创建一个覆盖数组长度的斐波那契队列.
	fibM2, fibM1, fibM := 0, 1, 1
	for fibM < len(array) {
		fibM2, fibM1 = fibM1, fibM
		fibM = fibM1 + fibM2
	}

	offset := -1
	for fibM2 > 1 {
		i := min2(offset+fibM2-fibM1, len(array)-1)
		if i > 0 && array[i] < array[offset+fibM2-fibM1] {
			fibM2, fibM1 = fibM1, fibM2-fibM1
			offset = i
		} else {
			fibM2, fibM1 = fibM2-fibM1, fibM1
		}
	}

	//使用插入排序对数组进行排序.
	for i := offset + 1; i < len(array); i++ {
		tmp := array[i]
		j := i - 1
		for j >= 0 && array[j] > tmp {
			array[j+1] = array[j]
			j--
		}
		array[j+1] = tmp
	}
	return array
}

func min2(x, y int) int {
	if x < y {
		return x
	}
	return y
}

3.2main方法:

func main() {
	array := []int{66, 8, 88, 55, 5, 28}
	search := data.FibonacciSearch(array)
	fmt.Printf("search array %v\n", search)
}

4.实战:

4.1方法:

func min2(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func FirstBadVersion(n int) int {
	fibM2 := 0
	fibM1 := 1
	fibM := fibM2 + fibM1
	//找到大于或等于n的最小斐波那契数.
	for fibM < n {
		fibM2 = fibM1
		fibM1 = fibM
		fibM = fibM1 + fibM2
	}
	index := -1
	//使用斐波那契数列执行搜索.
	for fibM > 1 {
		//计算指标
		i := min2(index+fibM2, n-1)
		//如果当前没有错误.则丢弃左侧部分向右移动.
		if !isBadVersion(i) {
			fibM = fibM1
			fibM1 = fibM2
			fibM2 = fibM - fibM1
			index = i
		} else {
			fibM = fibM2
			fibM1 = fibM1 - fibM2
			fibM2 = fibM - fibM1
		}
	}
	if fibM1 > 0 && index < (n-1) && isBadVersion(index+1) {
		return index + 1
	}
	return n
}

func isBadVersion(i int) bool {
	return i >= 5
}

4.2main方法:

func main() {
	n := 8
	version := data.FirstBadVersion(n)
	fmt.Printf("Version: %v \n", version)
}

东风不与周郎便.





如果大家喜欢我的分享的话.可以关注我的微信公众号

念何架构之路