and one way many network protocols achieve security is to encrypt mes- sages. Typicalcryptographicschemes for the secure transmission of mes- sages over such networks are based on the fact that no efficient algorithms are known for factoring large integers. Hence, if we can represent a secret message by a large prime number p, we can transmit, over the network, the numberr=p·q, whereq>pis another large prime number that acts as theencryption key. An eavesdropper who obtains the transmitted num- berron the network would have to factorrin order to figure out the secret messagep.
Using factoring to figure out a message is very difficult without knowing the encryption keyq. To understand why, consider the following naive factoring algorithm:
forp in range(2,r):
if r % p == 0: # if p divides r
return The secret message is p!
a. Suppose that the eavesdropper uses the above algorithm and has a computer that can carry out in 1 microsecond (1 millionth of a sec- ond) a division between two integers of up to 100 bits each. Give an estimate of the time that it will take in the worst case to decipher the secret messagepif the transmitted messagerhas 100 bits.
b. What is the worst-case time complexity of the above algorithm?
Since the input to the algorithm is just one large numberr, assume that the input sizenis the number of bytes needed to storer, that is, n=(log2r)/8+1, and that each division takes timeO(n). C-3.45 A sequenceS contains n−1 unique integers in the range[0,n−1], that
is, there is one number from this range that is not inS. Design anO(n)- time algorithm for finding that number. You are only allowed to useO(1) additional space besides the sequenceSitself.
C-3.46 Al says he can prove that all sheep in a flock are the same color:
Base case:One sheep. It is clearly the same color as itself.
Induction step: A flock ofnsheep. Take a sheep,a, out. The remaining n−1 are all the same color by induction. Now put sheepaback in and take out a different sheep,b. By induction, then−1 sheep (now witha) are all the same color. Therefore, all the sheep in the flock are the same color. What is wrong with Al’s “justification”?
C-3.47 LetS be a set of n lines in the plane such that no two are parallel and no three meet in the same point. Show, by induction, that the lines inS determineΘ(n2)intersection points.
C-3.48 Consider the following “justification” that the Fibonacci function, F(n) (see Proposition 3.20) isO(n):
Base case(n≤2): F(1) =1 andF(2) =2.
Induction step(n>2): Assume claim true forn<n. Considern.F(n) = F(n−2) +F(n−1). By induction,F(n−2)isO(n−2)andF(n−1)is O(n−1). Then,F(n)isO((n−2)+ (n−1)), by the identity presented in Exercise R-3.11. Therefore,F(n)isO(n).
What is wrong with this “justification”?
C-3.49 Consider the Fibonacci function, F(n) (see Proposition 3.20). Show by induction thatF(n)isΩ((3/2)n).
C-3.50 Letp(x)be a polynomial of degreen, that is,p(x) =∑ni=0aixi. (a) Describe a simpleO(n2)-time algorithm for computing p(x).
(b) Describe anO(nlogn)-time algorithm for computingp(x), based upon a more efficient calculation ofxi.
(c) Now consider a rewriting ofp(x)as
p(x) =a0+x(a1+x(a2+x(a3+···+x(an−1+xan)···))), which is known asHorner’s method. Using the big-Oh notation, charac- terize the number of arithmetic operations this method executes.
C-3.51 Show that the summation∑ni=1logiisO(nlogn). C-3.52 Show that the summation∑ni=1logiisΩ(nlogn).
C-3.53 An evil king hasn bottles of wine, and a spy has just poisoned one of them. Unfortunately, they do not know which one it is. The poison is very deadly; just one drop diluted even a billion to one will still kill. Even so, it takes a full month for the poison to take effect. Design a scheme for determining exactly which one of the wine bottles was poisoned in just one month’s time while expendingO(logn)taste testers.
C-3.54 A sequenceScontainsnintegers taken from the interval[0,4n], with repe- titions allowed. Describe an efficient algorithm for determining an integer valuekthat occurs the most often inS. What is the running time of your algorithm?
Projects
P-3.55 Perform an experimental analysis of the three algorithmsprefix average1, prefix average2, andprefix average3, from Section 3.3.3. Visualize their running times as a function of the input size with a log-log chart.
P-3.56 Perform an experimental analysis that compares the relative running times of the functions shown in Code Fragment 3.10.
Chapter Notes 147 P-3.57 Perform experimental analysis to test the hypothesis that Python’ssorted
method runs inO(nlogn)time on average.
P-3.58 For each of the three algorithms,unique1, unique2, andunique3, which solve the element uniqueness problem, perform an experimental analysis to determine the largest value ofnsuch that the given algorithm runs in one minute or less.
Chapter Notes
The big-Oh notation has prompted several comments about its proper use [19, 49, 63].
Knuth [64, 63] defines it using the notationf(n) =O(g(n)), but says this “equality” is only
“one way.” We have chosen to take a more standard view of equality and view the big-Oh notation as a set, following Brassard [19]. The reader interested in studying average-case analysis is referred to the book chapter by Vitter and Flajolet [101]. For some additional mathematical tools, please refer to Appendix B.
4 Recursion
Contents
4.1 Illustrative Examples . . . 150 4.1.1 The Factorial Function . . . 150 4.1.2 Drawing an English Ruler . . . 152 4.1.3 Binary Search . . . 155 4.1.4 File Systems . . . 157 4.2 Analyzing Recursive Algorithms . . . 161 4.3 Recursion Run Amok . . . 165 4.3.1 Maximum Recursive Depth in Python . . . 168 4.4 Further Examples of Recursion . . . 169 4.4.1 Linear Recursion . . . 169 4.4.2 Binary Recursion . . . 174 4.4.3 Multiple Recursion . . . 175 4.5 Designing Recursive Algorithms . . . 177 4.6 Eliminating Tail Recursion . . . 178 4.7 Exercises . . . 180
149 One way to describe repetition within a computer program is the use of loops, such as Python’swhile-loop andfor-loop constructs described in Section 1.4.2. An entirely different way to achieve repetition is through a process known asrecursion.
Recursion is a technique by which a function makes one or more calls to itself during execution, or by which a data structure relies upon smaller instances of the very same type of structure in its representation. There are many examples of recursion in art and nature. For example, fractal patterns are naturally recursive. A physical example of recursion used in art is in the Russian Matryoshka dolls. Each doll is either made of solid wood, or is hollow and contains another Matryoshka doll inside it.
In computing, recursion provides an elegant and powerful alternative for per- forming repetitive tasks. In fact, a few programming languages (e.g., Scheme, Smalltalk) do not explicitly support looping constructs and instead rely directly on recursion to express repetition. Most modern programming languages support functional recursion using the identical mechanism that is used to support tradi- tional forms of function calls. When one invocation of the function make a recur- sive call, that invocation is suspended until the recursive call completes.
Recursion is an important technique in the study of data structures and algo- rithms. We will use it prominently in several later chapters of this book (most notably, Chapters 8 and 12). In this chapter, we begin with the following four il- lustrative examples of the use of recursion, providing a Python implementation for each.
• Thefactorial function (commonly denoted asn!) is a classic mathematical function that has a natural recursive definition.
• AnEnglish rulerhas a recursive pattern that is a simple example of a fractal structure.
• Binary searchis among the most important computer algorithms. It allows us to efficiently locate a desired value in a data set with upwards of billions of entries.
• Thefile systemfor a computer has a recursive structure in which directories can be nested arbitrarily deeply within other directories. Recursive algo- rithms are widely used to explore and manage these file systems.
We then describe how to perform a formal analysis of the running time of a recursive algorithm and we discuss some potential pitfalls when defining recur- sions. In the balance of the chapter, we provide many more examples of recursive algorithms, organized to highlight some common forms of design.