Explore new routes Fibonacci Fibonacci number sequence

Only with water mist washing clean heart, glory will illuminate the original dream.

                                                                                          - Garcia Marquez

Recently addicted to the algorithm, always thinking about the implementation and optimization, today thought Fibonacci number, the original did not ye think, now go back and see if you can output something new? !

What is the Fibonacci number Everyone knows that I am beginning to understand and realize that the time to write a recursive addition to achieve, the following code is not strange:

func recursive(num int) int {
	if num < 1 {
		return 0
	}

	if num == 1 || num == 2 {
		return 1
	}
	return recursive(num-1) + recursive(num-2)
}

Analysis of ideas : to pass a number, it is the top-down began to count, such as the incoming 40, it will first come first 40-1 and 40-2, namely 29 and 28 the two numbers, with the value passed to the recursive function is gradually reduced, until the end 12 is reduced to only the real or the calculated. The whole process is actually a binary tree.

Process Analysis : A Case Study Incoming 5:! 5 = 1 because recursively Accordingly, counted 4 and 3 two numbers, i.e. in a return recursive code (4) + recursive (3)and while the recursive this left half of (4) passing i.e. 4, since 4 = 1, recursively, the code executes return recursive (3) + recursive (Note that the implementation of a recursive (2);! and right recursive this half portion (3), because 3! = 1, recursively, the code is a return recursive (2) + recursive (Note here again the implementation of a recursive (2), in other words, a more incoming a small number, in which the same calculation may be executed multiple times, if you pass a large, recursive (xx-1) after so very, very much recursive (xx) and its decomposition, recursive (xx-2) etc. will be executed many times. If the incoming 40, through projections, drawn binary tree as follows:

Calculation of the circle portion is repeated a plurality of times. Incoming number is small so no big problem, if the value is greater, the tree will be very large, apparently double counting value very much.

Improvement programs : Since so many will have to calculate is the same process, then I calculate for the first time when you can first record Well, next time again performed to check if I have this value take over direct sum not like slightly? !

To achieve the following:

func testFib1(num int) int {
	if num < 1 {
		return 0
	}

	backMap := make(map[int]int)
	return test(backMap, num)
}

func test(backMap map[int]int, num int) int {
	if num == 1 || num == 2 {
		return 1
	}

	if backMap[num] != 0 { // 已经计算过的直接获取之前的计算结果,避免重复计算
		return backMap[num]
	}

	// 如果传入的是40,那么对于3-40之间每个test(x)来说只执行了一遍,test方法共执行40-2=38次,时间复杂度为O(n)
	backMap[num] = test(backMap, num-1) + test(backMap, num-2) // 如果没有,那么算一下,存到map里记录下来
	return backMap[num]
}

This idea is still the top-down calculation, to avoid a lot of double counting process, of course, we can also reverse thrust to achieve bottom-up and let the passed value as the loop condition to see:

func testFib2(num int) int {
	if num < 1 {
		return 0
	}
	if num == 1 || num == 2 {
		return 1
	}

	// left 和 right,每次较大的是right,因为right不仅要和left相加,还会和他的right相加
	left, right, res := 1, 1, 0
	// 最多循环num-3+1次,如果传入的是40,那么循环了38次,时间规模即循环次数,时间复杂度为O(n)
	// 循环从第3个数开始,i=3执行结束时保证产生的res也就是第3个数=2即可,这样逻辑立即就浮现在眼前了
	for i := 3; i <= num; i++ {
		res = left + right
		left, right = right, res
	}

	return res
}

This two improvement programs came out to witness the miracle of the moment! Three ways to look at than time consuming (here to see a larger value when, as incoming values ​​are very small little effect):

func main() {
	t1 := time.Now().UnixNano()
	fmt.Println(recursive(40))
	t2 := time.Now().UnixNano()
	fmt.Println("传统计算(自顶向下计算)耗时:", (t2-t1)/1e6, "毫秒")

	t3 := time.Now().UnixNano()
	fmt.Println(testFib1(40))
	t4 := time.Now().UnixNano()
	fmt.Println("改良后(自顶向下计算)耗时:", (t4-t3)/1e6, "毫秒")

	t5 := time.Now().UnixNano()
	fmt.Println(testFib2(40))
	t6 := time.Now().UnixNano()
	fmt.Println("改良后(自底向上计算)耗时:", (t6-t5)/1e6, "毫秒")
}

Print Console:

102334155
传统计算(自顶向下计算)耗时: 631 毫秒
102334155
改良后(自顶向下计算)耗时: 0 毫秒
102334155
改良后(自底向上计算)耗时: 0 毫秒

Process finished with exit code 0

Flattered! ! !

Summary: When you want to optimize something, or trying to do something better, you can look carefully stroked the process before, and see what impact the drawbacks, there are drawbacks to find countermeasures get away.

Welcome my dear friend to discuss!

 

 

 

He published 182 original articles · won praise 132 · views 90000 +

Guess you like

Origin blog.csdn.net/HYZX_9987/article/details/104776595