On the first day, the monkey picked up a few peaches and immediately ate half of them. If they were not satisfied, they ate one more. In the morning of the next day, I ate half of the remaining peaches.
I ate one. In the future, eat the remaining half of the day before and add one. There is just one remaining in 10th days. How many peaches have monkeys picked on the first day?
Analysis: This is a set of very classicAlgorithmThis question is a manifestation of the recursive thinking in algorithm thinking. There are two forms of recursion: forward and backward.
We can find the recursive formula to solve the problem.
So that S10 = 1, it is easy to see S9 = 2 (S10 + 1), simplify it
S9 = 2s10 + 2
S8 = 2s9 + 2
.....
Sn = 2Sn + 1 + 2
Yao Xiang Gong Jin said that recursion is the most concise and easy to understand. Well, just use recursion to give it a try:
1 Class Program 2 { 3 Static Void Main ( String [] ARGs) 4 { 5 Int Sum = sumpeach ( 1 ); 6 7 Console. writeline ( " Peaches picked on the first day: {0} " , Sum ); 8 9 Console. Read (); 10 } 11 12 // Recursion 13 Static Int Sumpeach ( Int Day) 14 { 15 If (Day = 10 ) 16 Return 1 ; 17 18 Return 2 * Sumpeach (day + 1 ) + 2 ; 19 } 20 }
When we were playing with recursion, the teacher said linear recursion would press the "variables, parameters, and return values" in the "delivery" process. If the "delivery" fails, the stack will accumulate more,
In the end, the system's default stack space in the window is 1 MB.
So what is the solution? Tail recursion. Let's continue.Code:
1 Class Program 2 { 3 Static Void Main ( String [] ARGs) 4 { 5 Int Sum = sumpeachtail ( 1 , 1 ); 6 7 Console. writeline ( " Peaches picked on the first day: {0} " , Sum ); 8 9 Console. Read (); 10 } 11 12 // Tail recursion 13 Static Int Sumpeachtail ( Int Day, Int Total) 14 { 15 If (Day = 10 ) 16 Return Total; 17 18 // Calculate the current value and pass it to the next layer. 19 Return Sumpeachtail (day + 1 , 2 * Total + 2 ); 20 } 21 }
So what is the difference between the two types of recursion? Speak.
We can clearly see the difference between "linear recursion" and "tail recursion". What are the essential differences? In the tail recursion process, the current
The results of the layer are calculated and passed down. Theoretically, after being passed to the next layer, the parameter values of the previous layer are no longer necessary. You can clear the variables in the previous Layer
The stack space is used, so the final effect will never be stackoverflowexception, but whether it actually has this effect depends on compilation.ProgramWhether
I have optimized it for you.
Next we will change day = 10 to day = int. maxvalue, and run the program to see it:
Unfortunately, if there is a picture of the truth and an exception is thrown, of course I am a cainiao and I can't understand the Assembly. You can also discuss it. Currently, I personally think the C # compiler has not given
I am doing this optimization:-D.
In the next step, we need to calculate the time complexity of this recursion. There are three kinds of time complexity for "recursion:
1. replacement method.
2. Recursive tree method.
3. Main Theorem.
I will discuss the replacement method as follows:
①: Guess the upper or lower bound of recursive complexity.
②: Use mathematical induction to prove that your complexity is correct.
In order to be universal, we will reverse the question of "monkey eat peach", that is, we know S1, and calculate S10. Of course, the principle is the same. The general formula is as follows:
Tn = 2tn-1 + 2 ①
If Tn = O (n) ②
Then there must be a natural number of C> 0
TN <= Co (n) = cn ③
③ Substitute ① knowledge
TN <= 2C (n-1) + 2 = 2cn-2c + 2
= Cn-C + 1
= Cn-(c-1)
When C> = 1, TN <= Cn
Finally, the time complexity of recursion is O (n ).