算法导论第三版参考答案

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/sophies671207/article/details/85221118

1.1-1

Give a real-world example that requires sorting or a real-world example that requires computing a convex hull.

  • Sorting: browse the price of the restaurants with ascending prices on NTU street.
  • Convex hull: computing the diameter of set of points.

1.1-2

Other than speed, what other measures of efficiency might one use in a real-world setting?

Memory efficiency and coding efficiency.

1.1-3

Select a data structure that you have seen previously, and discuss its strengths and limitations.

Linked-list:

  • Strengths: insertion and deletion.
  • Limitations: random access.

1.1-4

How are the shortest-path and traveling-salesman problems given above similar? How are they different?

  • Similar: finding path with shortest distance.
  • Different: traveling-salesman has more constrains.

1.1-5

Come up with a real-world problem in which only the best solution will do. Then come up with one in which a solution that is ‘‘approximately’’ the best is good enough.

  • Best: find the GCD of two positive integer numbers.
  • Approximately: find the solution of differential equations.

1.2-1

Give an example of an application that requires algorithmic content at the application level, and discuss the function of the algorithms involved.

Drive navigation.

1.2-2

Suppose we are comparing implementations of insertion sort and merge sort on the same machine. For inputs of size nn , insertion sort runs in 8n28n^2 steps, while merge sort runs in 64nlgn64n\lg n steps. For which values of nn does insertion sort beat merge sort?

\begin{align}
8n^2 & < 64n\lg n \\
2^n & < n^8 \\
n & \le 43.
\end{align}

1.2-3

What is the smallest value of nn such that an algorithm whose running time is 100n2100n^2 runs faster than an algorithm whose running time is 2n2^n on the same machine?

\begin{align}
100n^2 & < 2^n \\
n & \ge 15.
\end{align}

For each function f(n)f(n) and time tt in the following table, determine the largest size nn of a problem that can be solved in time tt, assuming that the algorithm to solve the problem takes f(n)f(n) microseconds.

For each function f(n)f(n) and time tt in the following table, determine the largest size nn of a problem that can be solved in time tt, assuming that the algorithm to solve the problem takes f(n)f(n) microseconds.

2-1

Although merge sort runs in Θ(nlgn)\Theta(n\lg n) worst-case time and insertion sort runs in Θ(n2)\Theta(n^2) worst-case time, the constant factors in insertion sort can make it faster in practice for small problem sizes on many machines. Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when subproblems become sufficiently small. Consider a modification to merge sort in which n/kn / k sublists of length kk are sorted using insertion sort and then merged using the standard merging mechanism, where kk is a value to be determined.

a. Show that insertion sort can sort the n/kn / k sublists, each of length kk, in Θ(nk)\Theta(nk) worst-case time.

b. Show how to merge the sublists in Θ(nlg(n/k))\Theta(n\lg(n / k)) worst-case time.

c. Given that the modified algorithm runs in Θ(nk+nlg(n/k))\Theta(nk + n\lg(n / k)) worst-case time, what is the largest value of kk as a function of nn for which the modified algorithm has the same running time as standard merge sort, in terms of Θ\Theta-notation?

d. How should we chosse kk in practice?

a. Insertion sort takes Θ(k2)\Theta(k^2) time per kk-element list in the worst case. Therefore, sorting n/kn / k lists of kk elements each takes Θ(k2n/k)=Θ(nk)\Theta(k^2n / k) = \Theta(nk) worst-case time.

b. Just extending the 22-list merge to merge all the lists at once would take Θ(n(n/k))=Θ(n2/k)\Theta(n \cdot(n / k)) = \Theta(n^2/k) time (nn from copying each element once into the result list, n/kn / k from examining n/kn / k lists at each step to select next item for result list).

To achieve Θ(nlg(n/k))\Theta(n\lg(n / k))-time merging, we merge the lists pairwise, then merge the resulting lists pairwise, and so on, until there’s just one list. The pairwise merging requires Θ(n)\Theta(n) work at each level, since we are still working on nn elements, even if they are partitioned among sublists. The number of levels, starting with n/kn / k lists (with kk elements each) and finishing with 1 list (with nn elements), is lg(n/k)\lceil \lg(n / k) \rceil. Therefore, the total running time for the merging is Θ(nlg(n/k))\Theta(n\lg(n / k)).

c. The modified algorithm has the same asymptotic running time as standard merge sort when Θ(nk+nlg(n/k))=Θ(nlgn)\Theta(nk + n\lg(n / k)) = \Theta(n\lg n). The largest asymptotic value of kk as a function of nn that satisfies this condition is k=Θ(lgn)k = \Theta(\lg n).

To see why, first observe that kk cannot be more than Θ(lgn)\Theta(\lg n) (i.e., it can’t have a higher-order term than lgn\lg n), for otherwise the left-hand expression wouldn’t be Θ(nlgn)\Theta(n\lg n) (because it would have a higher-order term than nlgnn\lg n). So all we need to do is verify that k=Θ(lgn)k = \Theta(\lg n) works, which we can do by plugging k=lgnk = \lg n into

Θ(nk+nlg(n/k))=Θ(nk+nlgnnlgk)\Theta(nk + n\lg(n / k)) = \Theta(nk + n\lg n - n\lg k)

to get

Θ(nlgn+nlgnnlglgn)=Θ(2nlgnnlglgn),\Theta(n\lg n + n\lg n - n\lg\lg n) = \Theta(2n\lg n - n\lg\lg n),

which by taking just the high-order term and ignorin the constant coefficient, equals Θ(nlgn)\Theta(n\lg n).

d. In practice, kk should be the largest list length on which insertion sort is faster than merge sort.

2-2

Bubblesort is a popular, but inefficient, sorting algorithm. It works by repeatedly swapping adjacent elements that are out of order.

BUBBLESORT(A)
    for i = 1 to A.length - 1 
        for j = A.length downto i + 1 
            if A[j] < A[j - 1]
                exchange A[j] with A[j - 1]

a. Let AA&#x27; denote the output of BUBBLESORT(A)\text{BUBBLESORT}(A) To prove that BUBBLESORT\text{BUBBLESORT} is correct, we need to prove that it terminates and that

(2.3)A[1]A[2]A[n],A&#x27;[1] \le A&#x27;[2] \le \cdots \le A&#x27;[n], \tag{2.3}

where n=A.lengthn = A.length. In order to show that BUBBLESORT actually sorts, what else do we need to prove?

The next two parts will prove inequality (2.3)\text{(2.3)}.

b. State precisely a loop invariant for the for loop in lines 2–4, and prove that this loop invariant holds. Your proof should use the structure of the loop invariant proof presented in this chapter.

c. Using the termination condition of the loop invariant proved in part (b), state a loop invariant for the for loop in lines 1–4 that will allow you to prove inequality (2.3)\text{(2.3)}. Your proof should use the structure of the loop invariant proof presented in this chapter.

d. What is the worst-case running time of bubblesort? How does it compare to the running time of insertion sort?

a. We need to show that the elements of AA&#x27; form a permutation of the elements of AA.

b. Loop invariant: At the start of each iteration of the for loop of lines 2–4, A[j]=minA[k]:jknA[j] = \min\\{A[k]: j \le k \le n\\} and the subarray A[j..n]A[j..n] is a permutation of the values that were in A[j..n]A[j..n] at the time that the loop started.

Initialization: Initially, j=nj = n, and the subarray A[j..n]A[j..n] consists of single element A[n]A[n]. The loop invariant trivially holds.

Maintenance: Consider an iteration for a given value of jj. By the loop invariant, A[j]A[j] is the smallest value in A[j..n]A[j..n]. Lines 3–4 exchange A[j]A[j] and A[j1]A[j - 1] if A[j]A[j] is less than A[j1]A[j - 1], and so A[j1]A[j - 1] will be the smallest value in A[j1..n]A[j - 1..n] afterward. Since the only change to the subarray A[j1..n]A[j - 1..n] is this possible exchange, and the subarray A[j..n]A[j..n] is a permutation of the values that were in A[j..n]A[j..n] at the time that the loop started, we see that A[j1..n]A[j - 1..n] is a permutation of the values that were in A[j1..n]A[j - 1..n] at the time that the loop started. Decrementing jj for the next iteration maintains the invariant.

Termination: The loop terminates when jj reaches ii. By the statement of the loop invariant, A[i]=minA[k]:iknA[i] = \min\\{A[k]: i \le k \le n\\} and A[i..n]A[i..n] is a permutation of the values that were in A[i..n]A[i..n] at the time that the loop started.

c. Loop invariant: At the start of each iteration of the for loop of lines 1–4, the subarray A[1..i1]A[1..i - 1] consists of the i1i - 1 smallest values originally in A[1..n]A[1..n], in sorted order, and A[i..n]A[i..n] consists of the ni+1n - i + 1 remaining values originally in A[1..n]A[1..n].

Initialization: Before the first iteration of the loop, i=1i = 1. The subarray A[1..i1]A[1..i - 1] is empty, and so the loop invariant vacuously holds.

Maintenance: Consider an iteration for a given value of ii. By the loop invariant, A[1..i1]A[1..i - 1] consists of the ii smallest values in A[1..n]A[1..n], in sorted order. Part (b) showed that after executing the for loop of lines 2–4, A[i]A[i] is the smallest value in A[i..n]A[i..n], and so A[1..i]A[1..i] is now the ii smallest values originally in A[1..n]A[1..n], in sorted order. Moreover, since the for loop of lines 2–4 permutes A[i..n]A[i..n], the subarray A[i+1..n]A[i + 1..n] consists of the nin - i remaining values originally in A[1..n]A[1..n].

Termination: The for loop of lines 1–4 terminates when i=ni = n, so that i1=n1i - 1 = n - 1. By the statement of the loop invariant, A[1..i1]A[1..i - 1] is the subarray A[1..n1]A[1..n - 1], and it consists of the n1n - 1 smallest values originally in A[1..n]A[1..n], in sorted order. The remaining element must be the largest value in A[1..n]A[1..n], and it is in A[n]A[n]. Therefore, the entire array A[1..n]A[1..n] is sorted.

Note: Tn the second edition, the for loop of lines 1–4 had an upper bound of A.lengthA.length. The last iteration of the outer for loop would then result in no iterations of the inner for loop of lines 1–4, but the termination argument would simplify: A[1..i1]A[1..i - 1] would be the entire array A[1..n]A[1..n], which, by the loop invariant, is sorted.

d. The running time depends on the number of iterations of the for loop of lines 2–4. For a given value of ii, this loop makes nin - i iterations, and ii takes on the values 1,2,,n11, 2, \ldots, n - 1. The total number of iterations, therefore, is

\begin{align}
\sum_{i = 1}^{n - 1} (n - i)
& = \sum_{i = 1}^{n - 1} n - \sum_{i = 1}^{n - 1} i \\
& = n(n - 1) - \frac{n(n - 1)}{2} \\
& = \frac{n(n - 1)}{2} \\
& = \frac{n^2}{2} - \frac{n}{2}.
\end{align}

Thus, the running time of bubblesort is Θ(n2)\Theta(n^2) in all cases. The worst-case running time is the same as that of insertion sort.

2-3

The following code fragment implements Horner’s rule for evaluating a polynomial

\begin{align}
P(x) & = \sum_{k = 0}^n a_k x^k \\
& = a_0 + x(a_1 + x (a_2 + \cdots + x(a_{n - 1} + x a_n) \cdots)),
\end{align}

given the coefficients a0,a1,,ana_0, a_1, \ldots, a_n and a value of xx:

y = 0
for i = n downto 0
    y = a[i] + x * y

a. In terms of Θ\Theta-notation, what is the running time of this code fragment for Horner’s rule?

b. Write pseudocode to implement the naive polynomial-evaluation algorithm that computes each term of the polynomial from scratch. What is the running time of this algorithm? How does it compare to Horner’s rule

c. Consider the following loop invariant: At the start of each iteration of the for loop of lines 2-3,

y=k=0n(i+1)ak+i+1xk.y = \sum_{k = 0}^{n - (i + 1)} a_{k + i + 1} x^k.

Interpret a summation with no terms as equaling 00. Following the structure of the loop invariant proof presented in this chapter, use this loop invariant to show that, at termination, y=k=0nakxky = \sum_{k = 0}^n a_k x^k.

d. Conclude by arguing that the given code fragment correctly evaluates a polynomial characterized by the coefficients a0,a1,,ana_0, a_1, \ldots, a_n.

a. Θ(n)\Theta(n).

b.

NAIVE-HORNER()
    y = 0
    for k = 0 to n
        temp = 1
        for i = 1 to k
            temp = temp * x
            y = y + a[i] * m

The running time is Θ(n2)\Theta(n^2), because of the nested loop. It is obviously slower.

c. Initialization: It is pretty trivial, since the summation has no terms which implies y=0y = 0.

Maintenance: By using the loop invariant, in the end of the ii-the iteration, we have

\begin{align}
y & = a_i + x \sum_{k = 0}^{n - (i + 1)} a_{k + i + 1} x^k \\
& = a_i x^0 + \sum_{k = 0}^{n - i - 1} a_{k + i + 1} x^{k + 1} \\
& = a_i x^0 \sum_{k = 1}^{n - i} a_{k + i} x^k \\
& = \sum_{k = 0}^{n - i} a_{k + i} x^k.
\end{align}

Termination: The loop terminates at i=1i = -1. If we substitute,

y=k=0ni1ak+i+1xk=k=0nakxk.y = \sum_{k = 0}^{n - i - 1} a_{k + i + 1} x^k = \sum_{k = 0}^n a_k x^k.

d. The invariant of the loop is a sum that equals a polynomial with the given coefficients.

2-4

Let A[1..n]A[1..n] be an array of nn distinct numbers. If i&lt;ji &lt; j and A[i]&gt;A[j]A[i] &gt; A[j], then the pair (i,j)(i, j) is called an inversion of AA.

a. List the five inversions in the array 2,3,8,6,1\langle 2, 3, 8, 6, 1 \rangle.

b. What array with elements from the set 1,2,,n\\{1, 2, \ldots, n\\} has the most inversions? How many does it have?

c. What is the relationship between the running time of insertion sort and the number of inversions in the input array? Justify your answer.

d. Give an algorithm that determines the number of inversions in any permutation of nn elements in Θ(nlgn)\Theta(n\lg n) worst-case time. (Hint:\textit{Hint:} Modify merge sort).

a. The inversions are (1,5)(1,5), (2,5)(2,5), (3,4)(3,4), (3,5)(3,5), (4,5)(4,5). (Remember that inversions are specified by indices rather than by the values in the array.)

b. The array with elements from 1,2,,n\\{1, 2, \ldots, n\\} with the most inversions is n,n1,n2,,2,1\langle n, n - 1, n - 2, \ldots, 2, 1 \rangle. For all 1i&lt;jn1 \le i &lt; j \le n, there is an inversion (i,j)(i, j). The number of such inversions is (n2)=n(n1)/2\binom{n}{2} = n(n - 1) / 2.

c. Suppose that the array AA starts out with an inversion (k,j)(k, j). Then k&lt;jk &lt; j and A[k]&gt;A[j]A[k] &gt; A[j]. At the time that the outer for loop of lines 1–8 sets key=A[j]key = A[j], the value that started in A[k]A[k] is still somewhere to the left of A[j]A[j]. That is, it’s in A[i]A[i], where 1i&lt;j1 \le i &lt; j, and so the inversion has become (i,j)(i, j). Some iteration of the while loop of lines 5–7 moves A[i]A[i] one position to the right. Line 8 will eventually drop keykey to the left of this element, thus eliminating the inversion. Because line 5 moves only elements that are greater than keykey, it moves only elements that correspond to inversions. In other words, each iteration of the while loop of lines 5–7 corresponds to the elimination of one inversion.

d. We follow the hint and modify merge sort to count the number of inversions in Θ(nlgn)\Theta(n\lg n) time.

To start, let us define a merge-inversion as a situation within the execution of merge sort in which the MERGE\text{MERGE} procedure, after copying A[p..q]A[p..q] to LL and A[q+1..r]A[q + 1..r] to RR, has values xx in LL and yy in RR such that x&gt;yx &gt; y. Consider an inversion (i,j)(i, j), and let x=A[i]x = A[i] and y=A[j]y = A[j] , so that i&lt;ji &lt; j and x&gt;yx &gt; y. We claim that if we were to run merge sort, there would be exactly one mergeinversion involving xx and yy. To see why, observe that the only way in which array elements change their positions is within the MERGE\text{MERGE} procedure. Moreover, since MERGE\text{MERGE} keeps elements within LL in the same relative order to each other, and correspondingly for RR, the only way in which two elements can change their ordering relative to each other is for the greater one to appear in LL and the lesser one to appear in RR. Thus, there is at least one merge-inversion involving xx and yy. To see that there is exactly one such merge-inversion, observe that after any call of MERGE\text{MERGE} that involves both xx and yy, they are in the same sorted subarray and will therefore both appear in LL or both appear in RR in any given call thereafter. Thus, we have proven the claim.

We have shown that every inversion implies one merge-inversion. In fact, the correspondence between inversions and merge-inversions is one-to-one. Suppose we have a merge-inversion involving values xx and yy, where xx originally was A[i]A[i] and yy was originally A[j]A[j]. Since we have a merge-inversion, x&gt;yx &gt; y. And since xx is in LL and yy is in RR, xx must be within a subarray preceding the subarray containing yy. Therefore xx started out in a position ii preceding yy's original position jj, and so (i,j)(i, j) is an inversion.

Having shown a one-to-one correspondence between inversions and mergeinversions, it suffices for us to count merge-inversions.

Consider a merge-inversion involving yy in RR. Let zz be the smallest value in LL that is greater than yy. At some point during the merging process, zz and yy will be the “exposed” values in LL and RR, i.e., we will have z=L[i]z = L[i] and y=R[j]y = R[j] in line 13 of MERGE\text{MERGE}. At that time, there will be merge-inversions involving yy and L[i],L[i+1],L[i+2],,L[n1]L[i], L[i + 1], L[i + 2], \ldots, L[n_1], and these n1i+1n_1 - i + 1 merge-inversions will be the only ones involving yy. Therefore, we need to detect the first time that zz and yy become exposed during the MERGE\text{MERGE} procedure and add the value of n1i+1n_1 - i + 1 at that time to our total count of merge-inversions.

The following pseudocode, modeled on merge sort, works as we have just described. It also sorts the array AA.

COUNT-INVERSIONS(A, p, r)
    inversions = 0
    if p < r
        q = floor((p + r) / 2)
        inversions = inversions + COUNT-INVERSIONS(A, p, q)
        inversions = inversions + COUNT-INVERSIONS(A, q + 1, r)
        inversions = inversions + MERGE-INVERSIONS(A, p, q, r)
    return inversions
MERGE-INVERSIONS(A, p, q, r)
    n[1] = q - p + 1
    n[2] = r - q
    let L[1..n[1] + 1] and R[1..n[2] + 1] be new arrays
    for i = 1 to n[1]
        L[i] = A[p + i - 1]
    for j = 1 to n[2]
        R[j] = A[q + j]
    L[n[1] + 1] = ∞
    L[n[2] + 1] = ∞
    i = 1
    j = 1
    inversions = 0
    for k = p to r
        if R[j] < L[i]
            inversions = inversions + n[1] - i + 1
            A[k] = R[j]
            j = j + 1
        else A[k] = L[i]
            i = i + 1
    return inversions

The initial call is COUNT-INVERSIONS(A,1,n)\text{COUNT-INVERSIONS}(A, 1, n).

In MERGE-INVERSIONS\text{MERGE-INVERSIONS}, whenever R[j]R[j] is exposed and a value greater than R[j]R[j] becomes exposed in the LL array, we increase inersions by the number of remaining elements in LL. Then because R[j+1]R[j + 1] becomes exposed, R[j]R[j] can never be exposed again. We don’t have to worry about merge-inversions involving the sentinel \infty in RR, since no value in LL will be greater than \infty.

Since we have added only a constant amount of additional work to each procedure call and to each iteration of the last for loop of the merging procedure, the total running time of the above pseudocode is the same as for merge sort: Θ(nlgn)\Theta(n\lg n).

2.1-1

Using Figure 2.2 as a model, illustrate the operation of INSERTION-SORT\text{INSERTION-SORT} on the array A=31,41,59,26,41,58A = \langle 31, 41, 59, 26, 41, 58 \rangle.

\begin{align}
A & = \langle 31, 41, 59, 26, 41, 58 \rangle \\
A & = \langle 31, 41, 59, 26, 41, 58 \rangle \\
A & = \langle 31, 41, 59, 26, 41, 58 \rangle \\
A & = \langle 26, 31, 41, 59, 41, 58 \rangle \\
A & = \langle 26, 31, 41, 41, 59, 58 \rangle \\
A & = \langle 26, 31, 41, 41, 58, 59 \rangle
\end{align}

2.1-2

Rewrite the INSERTION-SORT\text{INSERTION-SORT} procedure to sort into nonincreasing instead of nondecreasing order.

INSERTION-SORT(A) 
    for j = 2 to A.length
        key = A[j]
        i = j - 1
        while i > 0 and A[i] < key
            A[i + 1] = A[i]
            i = i - 1
        A[i + 1] = key

2.1-3

Consider the searching problem:

Input: A sequence of nn numbers A=a1,a2,,anA = \langle a_1, a_2, \ldots, a_n \rangle and a value vv.

Output: An index ii such that v=A[i]v = A[i] or the special value NIL\text{NIL} if vv does not appear in AA.

Write pseudocode for linear search, which scans through the sequence, looking for vv. Using a loop invariant, prove that your algorithm is correct. Make sure that your loop invariant fulfills the three necessary properties.

LINEAR-SEARCH(A, v)
    for i = 1 to A.length
       if A[i] == v
            return i
    return NIL

Loop invariant: At the start of each iteration of the for loop, the subarray A[1..i1]A[1..i - 1] consists of elements that are different than vv.

Initialization: Initially the subarray is the empty array, so the prove is trivial.

Maintenance: On each step, we know that A[1..i1]A[1..i - 1] does not contain vv. We compare it with A[i]A[i]. If they are the same, we return ii, which is a correct result. Otherwise, we continue to the next step. We have already insured that A[1..i1]A[1..i - 1] does not contain vv and that A[i]A[i] is different from vv, so this step preserves the invariant.

Termination: The loop terminates when i&gt;A.lengthi &gt; A.length. Since ii increases by 11 and i&gt;A.lengthi &gt; A.length, we know that all the elements in AA have been checked and it has been found that vv is not among them. Thus, we return NIL\text{NIL}.

2.1-4

Consider the problem of adding two nn-bit binary integers, stored in two nn-element arrays AA and BB. The sum of the two integers should be stored in binary form in an (n+1)(n + 1)-element array CC. State the problem formally and write pseudocode for adding the two integers.

Input: An array of booleans A=a1,a2,,anA = \langle a_1, a_2, \ldots, a_n \rangle and an array of booleans B=b1,b2,,bnB = \langle b_1, b_2, \ldots, b_n \rangle, each representing an integer stored in binary format (each digit is a number, either 00 or 11, least-significant digit first) and each of length nn.

Output: An array C=c1,c2,,cn+1C = \langle c_1, c_2, \ldots, c_{n + 1} \rangle such that C=A+BC&#x27; = A&#x27; + B&#x27; where AA&#x27;, BB&#x27; and CC&#x27; are the integers, represented by AA, BB and CC.

ADD-BINARY(A, B)
    C = new integer[A.length + 1]
    carry = 0
    for i = 1 to A.length
        C[i] = (A[i] + B[i] + carry) % 2  // remainder
        carry = (A[i] + B[i] + carry) / 2 // quotient
    C[i] = carry
    return C

2.2-1

Express the function n3/1000100n2100n+3nn^3 / 1000 - 100n^2 - 100n + 3n in terms of Θ\Theta-notation.

Θ(n3)\Theta(n^3).

2.2-2

Consider sorting nn numbers stored in array AA by first finding the smallest element of AA and exchanging it with the element in A[1]A[1]. Then find the second smallest element of AA, and exchange it with A[2]A[2]. Continue in this manner for the first n1n - 1 elements of AA. Write pseudocode for this algorithm, which is known as selection sort. What loop invariant does this algorithm maintain? Why does it need to run for only the first n1n - 1 elements, rather than for all nn elements? Give the best-case and worst-case running times of selection sort in Θ\Theta-notation.

SELECTION-SORT(A)
    n = A.length
    for j = 1 to n - 1
        smallest = j
        for i = j + 1 to n
            if A[i] < A[smallest]
                smallest = i
        exchange A[j] with A[smallest]

The algorithm maintains the loop invariant that at the start of each iteration of the outer for loop, the subarray A[1..j1]A[1..j - 1] consists of the j1j - 1 smallest elements in the array A[1..n]A[1..n], and this subarray is in sorted order. After the first n1n - 1 elements, the subarray A[1..n]A[1..n] contains the smallest n1n - 1 elements, sorted, and therefore element A[n]A[n] must be the largest element.

The running time of the algorithm is Θ(n2)\Theta(n^2) for all cases.

2.2-3

Consider linear search again (see Exercise 2.1-3). How many elements of the in- put sequence need to be checked on the average, assuming that the element being searched for is equally likely to be any element in the array? How about in the worst case? What are the average-case and worst-case running times of linear search in Θ\Theta-notation? Justify your answers.

If the element is present in the sequence, half of the elements are likely to be checked before it is found in the average case. In the worst case, all of them will be checked. That is, n/2n / 2 checks for the average case and nn for the worst case. Both of them are Θ(n)\Theta(n).

2.2-4

How can we modify almost any algorithm to have a good best-case running time?

Modify the algorithm so it tests whether the input satisfies some special-case condition and, if it does, output a pre-computed answer. The best-case running time is generally not a good measure of an algorithm.

2.3-1

Using Figure 2.4 as a model, illustrate the operation of merge sort on the array A=3,41,52,26,38,57,9,49A = \langle 3, 41, 52, 26, 38, 57, 9, 49 \rangle.

[3][41][52][26][38][57][9][49] [3] \quad [41] \quad [52] \quad [26] \quad [38] \quad [57] \quad [9] \quad [49]

\downarrow

[341][2652][3857][949] [3|41] \quad [26| 52] \quad [38|57] \quad [9|49]

\downarrow

[3264152][9384957] [3|26|41|52] \quad [9 |38|49|57]

\downarrow

[39263841495257] [3|9|26|38|41|49|52|57]

2.3-2

Rewrite the MERGE\text{MERGE} procedure so that it does not use sentinels, instead stopping once either array LL or RR has had all its elements copied back to AA and then copying the remainder of the other array back into AA.

MERGE(A, p, q, r)
    n[1] = q - p + 1
    n[2] = r - q
    let L[1..n[1]] and R[1..n[2]] be new arrays
    for i = 1 to n[1]
        L[i] = A[p + i - 1]
    for j = 1 to n[2]
        R[j] = A[q + j]
    i = 1
    j = 1
    for k = p to r
        if i > n[1]
            A[k] = R[j]
            j = j + 1
        else if j > n[2]
            A[k] = L[i]
            i = i + 1
        else if L[i] ≤ R[j]
            A[k] = L[i]
            i = i + 1
        else
            A[k] = R[j]
            j = j + 1

2.3-3

Use mathematical induction to show that when nn is an exact power of 22, the solution of the recurrence

T(n)={2if n=2,2T(n/2)if n=2k,for k&gt;1 T(n) = \begin{cases} 2 &amp; \text{if } n = 2, \\\\ 2T(n / 2) &amp; \text{if } n = 2^k, \text{for } k &gt; 1 \end{cases}

is T(n)=nlgnT(n) = n\lg n.

The base case is when n=2n = 2, and we have nlgn=2lg2=21=2n\lg n = 2\lg 2 = 2 \cdot 1 = 2.

For the inductive step, our inductive hypothesis is that T(n/2)=(n/2)lg(n/2)T(n / 2) = (n / 2)\lg(n / 2). Then

\begin{align}
T(n) & = 2T(n / 2) + n \\
& = 2(n / 2) \lg(n / 2) + n \\
& = n(\lg n - 1) + n \\
& = n\lg n - n + n \\
& = n\lg n,
\end{align}

which completes the inductive proof for exact powers of 22.

2.3-4

We can express insertion sort as a recursive procedure as follows. In order to sort A[1..n]A[1..n], we recursively sort A[1..n1]A[1..n - 1] and then insert A[n]A[n] into the sorted array A[1..n1]A[1..n - 1]. Write a recurrence for the running time of this recursive version of insertion sort.

Since it takes Θ(n)\Theta(n) time in the worst case to insert A[n]A[n] into the sorted array A[1..n1]A[1..n - 1], we get the recurrence

T(n)={Θ(1)if n=1,T(n1)+Θ(n)if n&gt;1. T(n) = \begin{cases} \Theta(1) &amp; \text{if } n = 1, \\\\ T(n - 1) + \Theta(n) &amp; \text{if } n &gt; 1. \end{cases}

Although the exercise does not ask you to solve this recurrence, its solution is T(n)=Θ(n2)T(n) = \Theta(n^2).

2.3-5

Referring back to the searching problem (see Exercise 2.1-3), observe that if the sequence AA is sorted, we can check the midpoint of the sequence against vv and eliminate half of the sequence from further consideration. The binary search algorithm repeats this procedure, halving the size of the remaining portion of the sequence each time. Write pseudocode, either iterative or recursive, for binary search. Argue that the worst-case running time of binary search is Θ(lgn)\Theta(\lg n).

Procedure BINARY-SEARCH\text{BINARY-SEARCH} takes a sorted array AA, a value vv, and a range [low..high][low..high] of the array, in which we search for the value vv. The procedure compares to the array entry at the midpoint of the range and decides to eliminate half the range from further consideration. We give both iterative and recursive versions, each of which returns either an index ii such that A[i]=vA[i] = v, or NIL\text{NIL} if no entry of A[low..high]A[low..high] contains the value vv. The initial call to either version should have the parameters AA, vv, 11, nn.

ITERATIVE-BINARY-SEARCH(A, v, low, high)
    while low ≤ high
        mid = floor((low + high) / 2)
        if v == A[mid]
            return mid
        else if v > A[mid]
            low = mid + 1
        else high = mid - 1
    return NIL
RECURSIVE-BINARY-SEARCH(A, v, low, high)
    if low > high
        return NIL
    mid = floor((low + high) / 2)
    if v == A[mid]
        return mid
    else if v > A[mid]
        return RECURSIVE-BINARY-SEARCH(A, v, mid + 1, high)
    else return RECURSIVE-BINARY-SEARCH(A, v, low, mid - 1)

Both procedures terminate the search unsuccessfully when the range is empty (i.e., low&gt;highlow &gt; high) and terminate it successfully if the value vv has been found. Based on the comparison of vv to the middle element in the searched range, the search continues with the range halved. The recurrence for these procedures is therefore T(n)=T(n/2)+Θ(1)T(n) = T(n / 2) + \Theta(1), whose solution is T(n)=Θ(lgn)T(n) = \Theta(\lg n).

2.3-6

Observe that the while loop of lines 5–7 of the INSERTION-SORT\text{INSERTION-SORT} procedure in Section 2.1 uses a linear search to scan (backward) through the sorted subarray A[i..j1]A[i..j - 1]. Can we use a binary search (see Exercise 2.3-5) instead to improve the overall worst-case running time of insertion sort to Θ(nlgn)\Theta(n\lg n)?

The while loop of lines 5–7 of procedure INSERTION-SORT\text{INSERTION-SORT} scans backward through the sorted array A[1..j1]A[1..j - 1] to find the appropriate place for A[j]A[j]. The hitch is that the loop not only searches for the proper place for A[j]A[j], but that it also moves each of the array elements that are bigger than A[j]A[j] one position to the right (line 6). These movements can take as much as Θ(j)\Theta(j) time, which occurs when all the j1j - 1 elements preceding A[j]A[j] are larger than A[j]A[j]. We can use binary search to improve the running time of the search to Θ(lgj)\Theta(\lg j), but binary search will have no effect on the running time of moving the elements. Therefore, binary search alone cannot improve the worst-case running time of INSERTION-SORT\text{INSERTION-SORT} to Θ(nlgn)\Theta(n\lg n).

2.3-7 \star

Describe a Θ(nlgn)\Theta(n\lg n)-time algorithm that, given a set SS of nn integers and another integer xx, determines whether or not there exist two elements in SS whose sum is exactly xx.

The following algorithm solves the problem:

  1. Sort the elements in SS.
  2. Form the set KaTeX parse error: Expected '}', got 'EOF' at end of input: …\\{z: z = x - y for some KaTeX parse error: Expected 'EOF', got '}' at position 10: y \in S\\}̲.
  3. Sort the elements in SS&#x27;.
  4. Merge the two sorted sets SS and SS&#x27;.
  5. There exist two elements in SS whose sum is exactly xx if and only if the same value appears in consecutive positions in the merged output.

To justify the claim in step 4, first observe that if any value appears twice in the merged output, it must appear in consecutive positions. Thus, we can restate the condition in step 5 as there exist two elements in SS whose sum is exactly xx if and only if the same value appears twice in the merged output.

Suppose that some value ww appears twice. Then ww appeared once in SS and once in SS&#x27;. Because ww appeared in SS&#x27;, there exists some ySy \in S such that w=xyw = x - y, or x=w+yx = w + y. Since wSw \in S, the elements ww and yy are in SS and sum to xx.

Conversely, suppose that there are values w,ySw, y \in S such that w+y=xw + y = x. Then, since xy=wx - y = w, the value ww appears in SS&#x27;. Thus, ww is in both SS and SS&#x27;, and so it will appear twice in the merged output.

Steps 1 and 3 require Θ(nlgn)\Theta(n\lg n) steps. Steps 2, 4, 5, and 6 require O(n)O(n) steps. Thus the overall running time is O(nlgn)O(n\lg n).

A reader submitted a simpler solution that also runs in Θ(nlgn)\Theta(n\lg n) time. First, sort the elements in SS, taking Θ(nlgn)\Theta(n\lg n) time. Then, for each element yy in SS, perform a binary search in SS for xyx - y. Each binary search takes O(lgn)O(\lg n) time, and there are are most nn of them, and so the time for all the binary searches is O(nlgn)O(n\lg n). The overall running time is Θ(nlgn)\Theta(n\lg n).

Another reader pointed out that since SS is a set, if the value x/2x / 2 appears in SS, it appears in SS just once, and so x/2x / 2 cannot be a solution.

3.1-1

Let f(n)+g(n)f(n) + g(n) be asymptotically nonnegative functions. Using the basic definition of Θ\Theta-notation, prove that max(f(n),g(n))=Θ(f(n)+g(n))\max(f(n), g(n)) = \Theta(f(n) + g(n)).

First, let’s clarify what the function max(f(n),g(n))\max(f(n), g(n)) is. Let’s define the function h(n)=max(f(n),g(n))h(n) = \max(f(n), g(n)). Then

h(n)={f(n) if f(n)g(n),g(n) if f(n)&lt;g(n). h(n) = \begin{cases} f(n) &amp; \text{ if } f(n) \ge g(n), \\\\ g(n) &amp; \text{ if } f(n) &lt; g(n). \end{cases}

Since f(n)f(n) and g(n)g(n) are asymptotically nonnegative, there exists n0n_0 such that f(n)0f(n) \ge 0 and g(n)0g(n) \ge 0 for all nn0n \ge n_0. Thus for nn0n \ge n_0 , f(n)+g(n)f(n)0f(n) + g(n) \ge f(n) \ge 0 and f(n)+g(n)g(n)0f(n) + g(n) \ge g(n) \ge 0. Since for any particular nn, h(n)h(n) is either f(n)f(n) or g(n)g(n), we have f(n)+g(n)h(n)0f(n) + g(n) \ge h(n) \ge 0, which shows that

h(n)=max(f(n),g(n))c2(f(n)+g(n))h(n) = \max(f(n), g(n)) \le c_2(f(n) + g(n))

for all nn0n \ge n_0 (with c2=1c_2 = 1 in the definition of Θ\Theta).

Similarly, since for any particular nn, h(n)h(n) is the larger of f(n)f(n) and g(n)g(n), we have for all nn0n \ge n_0, 0f(n)h(n)0 \le f(n) \le h(n) and 0g(n)h(n)0 \le g(n) \le h(n). Adding these two inequalities yields 0f(n)+g(n)2h(n)0 \le f(n) + g(n) \le 2h(n), or equivalently 0(f(n)+g(n))/2h(n)0 \le (f(n) + g(n)) / 2 \le h(n), which shows that

h(n)=max(f(n),g(n))c1(f(n)+g(n))h(n) = \max(f(n), g(n)) \ge c_1(f(n) + g(n))

for all nn0n \ge n_0 (with c1=1/2c_1 = 1 / 2 in the definition of Θ\Theta).

3.1-2

Show that for any real constants aa and bb, where b&gt;0b &gt; 0,

(3.2)(n+a)b=Θ(nb).(n + a)^b = \Theta(n^b). \tag{3.2}

To show that (n+a)b=Θ(nb)(n + a)^b = \Theta(n^b), we want to find constants c1,c2,n0&gt;0c_1, c_2, n_0 &gt; 0 such that 0c1nb(n+a)bc2nb0 \le c_1 n^b \le (n + a)^b \le c_2 n^b for all nn0n \ge n_0.

Note that

\begin{align}
n + a & \le n + |a| & \\
& \le 2n & \text{ when } |a| \le n,
\end{align}

and

\begin{align}
n + a & \ge n - |a| & \\
& \ge \frac{1}{2}n & \text{ when } |a| \le \frac{1}{2}n.
\end{align}

Thus, when n2an \ge 2|a|,

012nn+a2n.0 \le \frac{1}{2}n \le n + a \le 2n.

Since b&gt;0b &gt; 0, the inequality still holds when all parts are raised to the power bb:

\begin{align}
0 \le \Big(\frac{1}{2}n\Big)^b & \le (n + a)^b \le (2n)^b, \\
0 \le \Big(\frac{1}{2}\Big)^b n^b & \le (n + a)^b \le 2^b n^b.
\end{align}

Thus, c1=(1/2)bc_1 = (1 / 2)^b, c2=2bc_2 = 2^b, and n0=2an_0 = 2|a| satisfy the definition.

3.1-3

Explain why the statement, ‘‘The running time of algorithm AA is at least O(n2)O(n^2),’’ is meaningless.

Let the running time be T(n)T(n). T(n)O(n2)T(n) \ge O(n^2) means that T(n)f(n)T(n) \ge f(n) for some function f(n)f(n) in the set O(n2)O(n^2). This statement holds for any running time T(n)T(n), since the function g(n)=0g(n) = 0 for all nn is in O(n2)O(n^2), and running times are always nonnegative. Thus, the statement tells us nothing about the running time.

3.1-4

Is 2n+1=O(2n)2^{n + 1} = O(2^n)? Is 22n=O(2n)2^{2n} = O(2^n)?

2n+1=O(2n)2^{n + 1} = O(2^n), but 22nO(2n)2^{2n} \ne O(2^n).

  • To show that 2n+1=O(2n)2^{n + 1} = O(2^n), we must find constants cc; n0&gt;0n_0 &gt; 0 such that

    02n+1c2n for all nn0. 0 \le 2^{n + 1} \le c \cdot 2^n \text{ for all } n \ge n_0.

    Since 2n+1=22n2^{n + 1} = 2 \cdot 2^n for all nn, we can satisfy the definition with c=2c = 2 and n0=1n_0 = 1.

  • To show that 22nO(2n)2^{2n} \ne O(2^n), assume there exist constants c,n0&gt;0c, n_0 &gt; 0 such that

    022nc2n for all nn0. 0 \le 2^{2n} \le c \cdot 2^n \text{ for all } n \ge n_0.

    Then 22n=2n2nc2n2nc2^{2n} = 2^n \cdot 2^n \le c \cdot 2^n \Rightarrow 2^n \le c. But no constant is greater than all 2n2^n, and so the assumption leads to a contradiction.

3.1-5

Prove Theorem 3.1.

The theorem states:

For any two functions f(n)f(n) and g(n)g(n), we have f(n)=Θ(g(n))f(n) = \Theta(g(n)) if and only if f(n)=O(g(n))f(n) = O(g(n)) and f(n)=Ω(g(n))f(n) = \Omega(g(n)).

From f=Θ(g(n))f = \Theta(g(n)), we have that

0c1g(n)f(n)c2g(n) for n&gt;n0.0 \le c_1 g(n) \le f(n) \le c_2g(n) \text{ for } n &gt; n_0.

We can pick the constants from here and use them in the definitions of OO and Ω\Omega to show that both hold.

From f(n)=Ω(g(n))f(n) = \Omega(g(n)) and f(n)=O(g(n))f(n) = O(g(n)), we have that

\begin{align}
& 0 \le c_3g(n) \le f(n) & \text{ for all } n \ge n_1 \\
\text{and } & 0 \le f(n) \le c_4g(n) & \text{ for all } n \ge n_2.
\end{align}

If we let n3=max(n1,n2)n_3 = \max(n_1, n_2) and merge the inequalities, we get

0c3g(n)f(n)c4g(n) for all n&gt;n3.0 \le c_3g(n) \le f(n) \le c_4g(n) \text{ for all } n &gt; n_3.

Which is the definition of Θ\Theta.

3.1-6

Prove that the running time of an algorithm is Θ(g(n))\Theta(g(n)) if and only if its worst-case running time is O(g(n))O(g(n)) and its best-case running time is Ω(g(n))\Omega(g(n)).

If TwT_w is the worst-case running time and TbT_b is the best-case running time, we know that

\begin{align}
& 0 \le c_1g(n) \le T_b(n) & \text{ for } n > n_b \\
\text{and } & 0 \le T_w(n) \le c_2g(n) & \text{ for } n > n_w.
\end{align}

Combining them we get

0c1g(n)Tb(n)Tw(n)c2g(n) for n&gt;max(nb,nw).0 \le c_1g(n) \le T_b(n) \le T_w(n) \le c_2g(n) \text{ for } n &gt; \max(n_b, n_w).

Since the running time is bound between TbT_b and TwT_w and the above is the definition of the Θ\Theta-notation, proved.

3.1-7

Prove o(g(n))w(g(n))o(g(n)) \cap w(g(n)) is the empty set.

We know that for any c&gt;0c &gt; 0,

\begin{align}
& \exists n_1 > 0: 0 \le f(n) < cg(n) \\
\text{and } & \exists n_2 > 0: 0 \le cg(n) < f(n).
\end{align}

If we pick n0=max(n1,n2)n_0 = \max(n_1, n_2), from the problem definition we get

f(n)&lt;cg(n)&lt;f(n).f(n) &lt; cg(n) &lt; f(n).

There is no solutions, which means that the intersection is the empty set.

3.1-8

We can extend our notation to the case of two parameters nn and mm that can go to infinity independently at different rates. For a given function g(n,m)g(n, m) we denote O(g(n,m))O(g(n, m)) the set of functions:

\begin{align}
O(g(n, m)) = \{f(n, m):
& \text{ there exist positive constants } c, n_0, \text{ and } m_0 \\
& \text{ such that } 0 \le f(n, m) \le cg(n, m) \\
& \text{ for all } n \ge n_0 \text{ or } m \ge m_0.\}
\end{align}

Give corresponding definitions for Ω(g(n,m))\Omega(g(n, m)) and Θ(g(n,m))\Theta(g(n, m)).

\begin{align}
\Omega(g(n, m)) = \{f(n, m):
& \text{ there exist positive constants } c, n_0, \text{ and } m_0 \\
& \text{ such that } 0 \le cg(n, m) \le f(n, m) \\
& \text{ for all } n \ge n_0 \text{ or } m \ge m_0.\}
\end{align}

\begin{align}
\Theta(g(n, m)) = \{f(n, m):
& \text{ there exist positive constants } c_1, c_2, n_0, \text{ and } m_0 \\
& \text{ such that } 0 \le c_1 g(n, m) \le f(n, m) \le c_2 g(n, m) \\
& \text{ for all } n \ge n_0 \text{ or } m \ge m_0.\}
\end{align}

3.2-1

Show that if f(n)f(n) and g(n)g(n) are monotonically increasing functions, then so are the functions f(n)+g(n)f(n) + g(n) and f(g(n))f(g(n)), and if f(n)f(n) and g(n)g(n) are in addition nonnegative, then f(n)g(n)f(n) \cdot g(n) is monotonically increasing.

\begin{align}
f(m) \le f(n) \quad \text{ for } m \le n \\
g(m) \le g(n) \quad \text{ for } m \le n, \\
\to f(m) + g(m) \le f(n) + g(n),
\end{align}

which proves the first function.

Then

f(g(m))f(g(n)) for mn.f(g(m)) \le f(g(n)) \text{ for } m \le n.

This is true, since g(m)&gt;g(n)g(m) &gt; g(n) and f(n)f(n) is monotonically increasing.

If both functions are nonnegative, then we can multiply the two equalities and we get

f(m)g(m)f(n)g(n).f(m) \cdot g(m) \le f(n) \cdot g(n).

3.2-2

Prove equation (3.16)\text{(3.16)}.

\begin{align}
a^{\log_b c} = a^\frac{\log_a c}{\log_a b} = (a^{\log_a c})^{\frac{1}{\log_a b}} = c^{\log_b a}
\end{align}

3.2-3

Prove equation (3.19)\text{(3.19)}. Also prove that nω(2n)n \ne \omega(2^n) and no(nn)n \ne o(n^n).

(3.19)lg(n!)=Θ(nlgn)\lg(n!) = \Theta(n\lg n) \tag{3.19}

We use Stirling’s approximation:

\begin{align}
\lg(n!)
& = \lg\Bigg(\sqrt{2\pi n}\Big(\frac{n}{e}\Big)^n\Big(1 + \Theta(\frac{1}{n})\Big)\Bigg) \\
& = \lg\sqrt{2\pi n } + \lg\Big(\frac{n}{e}\Big)^n + \lg\Big(1+\Theta(\frac{1}{n})\Big) \\
& = \Theta(\sqrt n) + n\lg{\frac{n}{e}} + \lg\Big(\Theta(1) + \Theta(\frac{1}{n})\Big) \\
& = \Theta(\sqrt n) + \Theta(n\lg n) + \Theta(\frac{1}{n}) \\
& = \Theta(n\lg n).
\end{align}

The other two are

n&gt;3:2n=222n times&lt;12n=n!n!=ω(2n).\forall n &gt; 3: 2^n = \underbrace{2 \cdot 2 \cdot \cdots \cdot 2}_\text{n times} &lt; 1 \cdot 2 \cdot \cdots \cdot n = n! \quad \Rightarrow \quad n! = \omega(2^n).

and

n&gt;1:n!=12n&lt;nnnn times=nnn!=o(nn).\forall n &gt; 1 : n! = 1 \cdot 2 \cdot \cdots n &lt; \underbrace{n \cdot n \cdot \cdots \cdot n}_\text{n times} = n^n \quad \Rightarrow \quad n! = o(n^n).

3.2-4 \star

Is the function lgn!\lceil \lg n \rceil! polynomially bounded? Is the function lglgn!\lceil \lg\lg n \rceil! polynomially bounded?

lgn!\lceil \lg n \rceil! is not polynomially bounded, but lglgn!\lceil \lg\lg n \rceil! is.

Proving that a function f(n)f(n) is polynomially bounded is equivalent to proving that lg(f(n))=O(lgn)\lg(f(n)) = O(\lg n) for the following reasons.

  • If ff is polynomially bounded, then there exist constants cc, kk, n0n_0 such that for all nn0n \ge n_0, f(n)cnkf(n) \le cn^k. Hence, lg(f(n))kclgn\lg(f(n)) \le kc\lg n, which, since cc and kk are constants, means that lg(f(n))=O(lgn)\lg(f(n)) = O(\lg n).
  • Similarly, if lg(f(n)=O(lgn)\lg(f(n) = O(\lg n), then ff is polynomially bounded.

In the following proofs, we will make use of the following two facts:

  1. lg(n!)=Θ(nlgn)\lg(n!) = \Theta(n\lg n) (by equation (3.19)\text{(3.19)}).
  2. lgn=Θ(lgn)\lceil \lg n \rceil = \Theta(\lg n), because
    • lgnlgn\lceil \lg n \rceil \ge \lg n
    • lgn&lt;lgn+12lgn for all n2\lceil \lg n \rceil &lt; \lg n + 1 \le 2\lg n \text{ for all } n \ge 2

\begin{align}
\lg(\lceil \lg n \rceil!) & = \Theta(\lceil \lg n \rceil \lg \lceil \lg n \rceil) \\
& = \Theta(\lg n\lg\lg n) \\
& = \omega(\lg n).
\end{align}

Therefore, lg(lgn!)O(lgn)\lg(\lceil \lg n \rceil!) \ne O(\lg n), and so lgn!\lceil \lg n \rceil! is not polynomially bounded.

\begin{align}
\lg(\lceil \lg\lg n \rceil!) & = \Theta(\lceil \lg\lg n \rceil \lg \lceil \lg\lg n \rceil) \\
& = \Theta(\lg\lg n\lg\lg\lg n) \\
& = o((\lg\lg n)^2) \\
& = o(\lg^2(\lg n)) \\
& = o(\lg n).
\end{align}

3.2-5 \star

Which is asymptotically larger: KaTeX parse error: Expected group after '^' at position 8: \lg(\lg^̲\*n) or KaTeX parse error: Expected group after '^' at position 4: \lg^̲\*(\lg n)?

KaTeX parse error: Expected group after '^' at position 4: \lg^̲\*(\lg n) is asymptotically larger because KaTeX parse error: Expected group after '^' at position 4: \lg^̲\*(\lg n) = \lg….

3.2-6

Show that the golden ratio ϕ\phi and its conjugate ϕ^\hat \phi both satisfy the equation x2=x+1x^2 = x + 1.

\begin{align}
\phi^2 - \phi - 1
& = \big(\frac{1 + \sqrt 5}{2}\big)^2 - \frac{1 + \sqrt 5}{2} - 1 \\
& = \frac{1 + 2\sqrt 5 + 5 - 2 - 2\sqrt 5 - 4}{4} \\
& = 0.
\end{align}
\begin{align}
\hat\phi^2 - \hat\phi - 1
& = \big(\frac{1 - \sqrt 5}{2}\big)^2 - \frac{1 - \sqrt 5}{2} - 1 \\
& = \frac{1 - 2\sqrt 5 + 5 - 2 + 2\sqrt 5 - 4}{4} \\
& = 0.
\end{align}

3.2-7

Prove by induction that the iith Fibonacci number satisfies the equality

Fi=ϕiϕ^i5,F_i = \frac{\phi^i - \hat\phi^i}{\sqrt 5},

where ϕ\phi is the golden ratio and ϕ^\hat\phi is its conjugate.

We have two base cases: i=0i = 0 and i=1i = 1. For i=0i = 0, we have

\frac{\phi^0 - \hat\phi^0}{\sqrt 5}
& = \frac{1 - 1}{\sqrt 5} \\
& = 0 \\
& = F_0,

and for i=1i = 1, we have

\begin{align}
\frac{\phi^1 - \hat\phi^1}{\sqrt 5}
& = \frac{(1 + \sqrt 5) - (1 - \sqrt 5)}{2\sqrt 5} \\
& = \frac{2\sqrt 5}{2\sqrt 5} \\
& = 1 \\
& = F_1.
\end{align}

For the inductive case, the inductive hypothesis is that Fi1(ϕi1ϕ^i1)/5F_{i - 1} - (\phi^{i - 1} - \hat\phi^{i - 1}) / \sqrt 5 and Fi2=(ϕi2ϕ^i2)/5F_{i - 2} = (\phi^{i - 2} - \hat\phi^{i - 2}) / \sqrt 5. We have

F_i & = F_{i - 1} + F_{i - 2} & \text{(equation (3.22)} \\
& = \frac{\phi^{i - 1} - \hat\phi^{i - 1}}{\sqrt 5} + \frac{\phi^{i - 2} - \hat\phi^{i - 2}}{\sqrt 5} & \text{(inductive hypothesis)} \\
& = \frac{\phi^{i - 2}(\phi + 1) - \hat\phi^{i - 2}(\hat\phi + 1)}{\sqrt 5} \\
& = \frac{\phi^{i - 2}\phi^2 - \hat\phi^{i - 2}\hat\phi^2}{\sqrt 5} & \text{(Exercise 3.2-6)} \\
& = \frac{\phi^i - \hat\phi^i}{\sqrt 5}.

3.2-8

Show that klnk=Θ(n)k\ln k = \Theta(n) implies k=Θ(n/lnn)k = \Theta(n / \ln n).

From the symmetry of Θ\Theta,

klnk=Θ(n)n=Θ(klnk).k\ln k = \Theta(n) \Rightarrow n = \Theta(k\ln k).

Let’s find lnn\ln n,

lnn=Θ(ln(klnk))=Θ(lnk+lnlnk)=Θ(lnk).\ln n = \Theta(\ln(k\ln k)) = \Theta(\ln k + \ln\ln k) = \Theta(\ln k).

Let’s divide the two,

nlnn=Θ(klnk)Θ(lnk)=Θ(klnklnk)=Θ(k).\frac{n}{\ln n} = \frac{\Theta(k\ln k)}{\Theta(\ln k)} = \Theta({\frac{k\ln k}{\ln k}}) = \Theta(k).

The last step above follows from the property that any polylogarithmic function grows more slowly than any positive polynomial function, i.e., that for constants a,b&gt;0a, b &gt; 0, we have lgb=o(na)\lg^b = o(n^a). Substitute lgn\lg n for nn, 22 for bb, and 11 for aa, giving lg2(lgn)=o(lgn)\lg^2(\lg n) = o(\lg n).

Therefore, lg(lglgn!)=O(lgn)\lg(\lceil \lg\lg n \rceil!) = O(\lg n), and so lglgn!\lceil \lg\lg n \rceil! is polynomially bounded.

3-1

Let
p(n)=i=0daini,p(n) = \sum_{i = 0}^d a_i n^i,

where ad&gt;0a_d &gt; 0, be a degree-dd polynomial in nn, and let kk be a constant. Use the definitions of the asymptotic notations to prove the following properties.

a. If kdk \ge d, then p(n)=O(nk)p(n) = O(n^k).

b. If kdk \le d, then p(n)=Ω(nk)p(n) = \Omega(n^k).

c. If k=dk = d, then p(n)=Θ(nk)p(n) = \Theta(n^k).

d. If k&gt;dk &gt; d, then p(n)=o(nk)p(n) = o(n^k).

e. If k&lt;dk &lt; d, then p(n)=ω(nk)p(n) = \omega(n^k).

Let’s see that p(n)=O(nd)p(n) = O(n^d). We need do pick c=ad+bc = a_d + b, such that

i=0d=adnd+ad1nd1++a1n+a0cnd.\sum\limits_{i = 0}^d = a_d n^d + a_{d - 1}n^{d - 1} + \cdots + a_1n + a_0 \le cn^d.

When we divide by ndn^d, we get

c=ad+bad+ad1n+ad2n2++a0nd.c = a_d + b \ge a_d + \frac{a_{d - 1}}n + \frac{a_{d - 2}}{n^2} + \cdots + \frac{a_0}{n^d}.

and

bad1n+ad2n2++a0nd.b \ge \frac{a_{d - 1}}n + \frac{a_{d - 2}}{n^2} + \cdots + \frac{a_0}{n^d}.

If we choose b=1b = 1, then we can choose n0n_0,

n0=max(dad1,dad2,,da0d).n_0 = \max(da_{d - 1}, d\sqrt{a_{d - 2}}, \ldots, d\sqrt[d]{a_0}).

Now we have n0n_0 and cc, such that

p(n)cndfor nn0,p(n) \le cn^d \quad \text{for } n \ge n_0,

which is the definition of O(nd)O(n^d).

By chosing b=1b = -1 we can prove the Ω(nd)\Omega(n^d) inequality and thus the Θ(nd)\Theta(n^d) inequality.

It is very similar to prove the other inequalities.

3-2

Indicate for each pair of expressions (A,B)(A, B) in the table below, whether AA is OO, oo, Ω\Omega, ω\omega, or Θ\Theta of BB. Assume that k1k \ge 1, ϵ&gt;0\epsilon &gt; 0, and c&gt;1c &gt; 1 are constants. Your answer should be in the form of the table with ‘‘yes’’ or ‘‘no’’ written in each box.

\begin{array}{ccccccc}
A & B & O & o & \Omega & \omega & \Theta \\
\hline
\lg^k n & n^\epsilon & yes & yes & no & no & no \\
n^k & c^n & yes & yes & no & no & no \\
\sqrt n & n^{\sin n} & no & no & no & no & no \\
2^n & 2^{n / 2} & no & no & yes & yes & no \\
n^{\lg c} & c^{\lg n} & yes & no & yes & no & yes \\
\lg(n!) & \lg(n^n) & yes & no & yes & no & yes
\end{array}

展开阅读全文

没有更多推荐了,返回首页