"Introduction to Algorithms" Reading notes--the 1th and 2 chapters after class

Source: Internet
Author: User

The first chapter turns from http://www.cnblogs.com/batteryhp/p/4654860.html

Study Questions

1-1 (comparison of elapsed time) determines the maximum size of the problem solved within the time t.

Above is the answer provided online.

Note the point:

1, the leftmost column is about the growth of n description, it is worth remembering the order of these growth, it is very useful, ah, it will be easy to learn a few points;

2, note that the 1s internal energy processing in order to increase the scale of N is 10 of 6 of the parties, remember that this result can be pushed to export the scale of other growth levels of processing;

3. Note that LG here refers to a logarithmic function with a base of 2.

By the way, make a LGN growth chart and feel it:

Originally want to put N and nlgn painting together, but the effect is not satisfied, such as:

I can see that NLGN is growing much faster than n! /False

Chapter II

2.1

2. Rewrite the insertion-sort to make it in ascending order.

In fact, just change the > in the while step to <.

Insertion-sortfor  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

3, find the problem, find a number in the array, linear find, write pseudo-code, and prove the loop invariant.

Find some valuefor i = 1 to a.length    if v = = A[i]        return i    else         return NIL

4, two binary numbers are stored in two arrays, sums the two numbers, and storing them in another array, writing formal descriptions and writing pseudo-code.

Write code (pro-Test valid):

#include <iostream>using namespace Std;const int Num = 10;int Main () {    int a[num] = {1,0,1,1,0,1,1,0,1,1};    int B[num] = {0,1,1,1,0,1,0,1,1,1};    int C[num + 1] = {0};    int flag = 0;    int i;    for (i = num-1;i >= 0;i--)    {        c[i+1] = A[i] + b[i] + flag;        if (c[i+1] > 1)        {            c[i+1] = c[i+1]%2;            flag = 1;        }        else            flag = 0;    }    C[0] = flag;    for (i = 0;i <= num;i++)        cout << c[i];    cout << Endl;    return 0;}

2.2

1, Theta (n^3)

2, sorting an array of n number, the rule is this, will be the smallest with the first exchange, the rest of the smallest with the second exchange ... Keep doing it until n-1, this algorithm is called the selection algorithm, requires writing loop invariant and pseudo-code, write the best worst run time magnitude.

Select algorithm Pseudo code for i = 1 to n-1    min = a[i] for    j = i + 1 to n        if a[j] < min            min = a[j]    Exchange A[i] An D min

Here is the answer to the wording of the same principle is the same:

In addition, the best and worst time to write. The best is that it has been lined up, this time also useless ah, also to find the minimum value ... So, the best is the worst n^2.

3, consider the linear lookup problem of 2.1-3, assuming that the element to be looked for can be any element in the array, the average need to check the input sequence of how many elements? What's the worst case scenario?

Solution: Intuitive thinking, the average word is half the number of elements, the worst is all. Can think of, now to choose an element, each element appears the probability is 1/n, need to check the number of 1, 2 ... n, then the expectation is (1+2+3...+n)/n is (n+1)/2 elements; worst case is n, nothing to say. In other words, the complexity of Theta (n).

According to the answer, because the general time in the first half of the search, half the time in the next half of the search, then the average is the middle of the value of it ~ ~

4. How can we modify (almost all) the algorithm but make it have the best running time?

Solution: Idea: is the best input bai ... Take a look at the answer: one can modify an algorithm to has a best-case running time by specializing it to handle a bestcase input efciently . Oh ...

2.3

2, rewrite the merge, when L or R is empty, the other group of data copied all to a.

MERGE  Pseudo-code n1 = q-p + 1n2 = r-q let l[1..n1] and R[1..N2] is new arrays//Because no "sentinel" is required, no more element for i = 1 to N1    L [I] = a[p + i-1]for j = 1 to n2    r[j] = a[q + j]i = 1j = 1for k = p to R    if i > N1                  //Add two here to judge while        J & lt;= n2            A[k] = r[j]            k = k + 1          //Do not forget to increment K and J, where K and J are separately incremented              j = j + 1       break    if J > N2        while I <= n1            a[k] = l[i]            k = k + 1            i = i + 1        break    if (I < N1 and J < N2)         //Note here The condition is judged, cannot be straight Pick up level Two if else, otherwise chaos
        If L[i] <= r[j]            a[k] = l[i]            i = i + 1        else a[k] = r[j]            j = j + 1
No "Sentinel" code.
#include <iostream> #include <time.h>void mergesort (int*, int,int); void MERGE (int*,int,int,int); using    namespace Std;int Main () {clock_t start, end;    start = Clock ();    int i;    int* arr = new int[100];    for (i = 0; i < i++) {arr[i] = 100-i;    } mergesort (arr,0,99);        for (i = 0; i < i++) {cout << arr[i] << "";        if (i% = = 9) {cout << "\ n";    }} Delete[]arr;    cout << "__________________" << Endl;    end = Clock ();    cout << "Run Time:" << (Double) (end-start)/clocks_per_sec << "s" << Endl;    return 0;}    void MergeSort (int* A, int p, int r) {int q;        if (P < r) {q = (p + r)/2;        MergeSort (A, p, q);        MergeSort (A, q + 1, R);    MERGE (A, p, Q, R);    }}void MERGE (int* arr, int p, int q, int r) {int N1 = q-p + 1;    int n2 = R-q;    int* left = new INT[N1]; int* right = new inT[N2];    int I, J;    for (i = 0; i < N1; i++) Left[i] = arr[p + i];    for (j = 0; J < N2; J + +) Right[j] = arr[q + j + 1];    i = 0;    j = 0;                            for (int k = p, k <= R; k++) {if (I >= N1) {while (J < N2) {                ARR[K] = Right[j];                k++;            j + +;        } break;                } if (J >= N2) {while (I < N1) {Arr[k] = Left[i];                k++;            i++;        } break; } if (I < N1 && J < N2) {if (Left[i] <= right[j]) {A                RR[K] = Left[i];            i++;                } else {arr[k] = right[j];            j + +;    }}} delete []left; delete []right;}

3, using the mathematical induction method to prove that the following formula is established, where T (n) =NLGN:

Prove:

(1) basic situation, n = 2 o'clock, T (n) =2lg2=2 was established;

(2) assume that when n = 2^k is established, i.e. t (2^k) = (2^k) LG (2^K), the following proves that when n = 2^ (k + 1) is established. T (2^ (k+1)) = 2T (2^k) +2^ (k+1) =2 ((2^k) LG (2^K)) +2^ (k+1) =2^ (k+1) (LG (2^K) +1) =2^ (k+1) (LG (2^K) +lg2) =2^ (k+1) (LG (2^K * 2)) = 2^ (k+1) (LG (2^ (k+1))), n=2^ (K+1) was also established.

4. We can represent the insertion sort as one of the following recursive processes. To sort A[1..N], recursively sort a[1..n-1], and then insert a[n] into the sorted array a[1..n-1]. Write a recursive for the worst case scenario of this recursive version of the insertion sort.

Solution: We consider the worst case, in the insertion sort, the original array is in reverse order, then each time there is a new number, you have to let it run to the top of the array already lined up ... Then the time complexity of inserting a new element is Theta (n), because the total to compare n-1 times, plus the judgment subscript does not cross, the complexity is N:

5, review the problem, 2.1-3, notice that if a has been sorted, then the new value V can be compared with the middle element of a, then the result of the comparison of the original array of half can no longer be examined. The binary lookup algorithm is the repetition of this process, halving the number of sequences at a time. Writes out the iteration or recursive pseudo-code of the binary lookup, and proves that the worst run time is Theta (LGN).

Solution: It is important to note that the array being looked up must be an already sorted array.

Recursive version of binary lookup BinarySearch (a,v,p,r) if P >= r and a[p]! = v    return nilelse     q = (p + r)/2    if a[q] = = v        retur n Q    else if A[Q] < v        return Binarysort (a,v,q+1,r)    else         return Binarysort (a,v,p,q-1)
Recursive version Two-point lookup code
#include <iostream> #include <time.h>using namespace Std;int binarysearc (int*, int, int, int); int main () {    clock_t start, end;    start = Clock ();    int* arr = new int[100];    int v =;    for (int i = 0; i < i++)    {        Arr[i] = i;    }    int position = Binarysort (arr, V, 0, max);        cout << position << Endl;    Delete[]arr;    cout << "__________________" << Endl;    end = Clock ();    cout << "Run Time:" << (Double) (end-start)/clocks_per_sec << "s" << Endl;    return 0;} int BinarySearch (int* arr, int v, int p, int r) {    if (P > R && arr[p]! = v)        return-1;    else    {        int q = (p + r)/2;        if (arr[q] = = v)            return q;        else if (Arr[q] < v)            Binarysort (arr, V, q + 1, r);        else            Binarysort (arr, V, p, q-1);    }        }

About Iteration Versions:

Iteration version of the binary find A is a arrayv is a valuep,r be the min and Max index of a iterationsearch (a,v,p,r) while    (P <= r)        Q = (p + r)/2        if a[q] = = v            return q        else if            v < a[q]            r = q        else            p = q    return NIL
Iterative versions of binary lookups
#include <iostream> #include <time.h>using namespace Std;int iterattionsearch (int*, int, int, int), int main ( ) {    clock_t start, end;    start = Clock ();    int* arr = new int[100];    int v =;    for (int i = 0; i < i++)    {        Arr[i] = i;    }    int position = Iterattionsearch (arr, V, 0, max);        cout << position << Endl;    Delete[]arr;    cout << "__________________" << Endl;    end = Clock ();    cout << "Run Time:" << (Double) (end-start)/clocks_per_sec << "s" << Endl;    return 0;} int Iterattionsearch (int* arr, int v, int p, int r) {while    (P <= r)    {        int q = (p + r)/2;        if (arr[q] = = v)            return q;        else if (Arr[q] < v)            p = q + 1;        else            r = q-1;    }        }

Here's the worst time complexity:

An array of n of elements, the worst need to be 2*LGN times 2 to get results, so the worst time complexity is Theta (LGN). This considers M-point lookups with a time complexity of M*LGM (n). LGM is a logarithmic function based on M, so what is the shortest time for a given n,m? Some experiments have been made to show that the m=3 function M*LGM (n) is the smallest, or the time complexity is lowest, but the efficiency is said to be not the highest. Have time to give it a try ~

6, in the insertion sort, for already ordered a[1..n-1], need to linear scan this already arranged sequence. Now you want to optimize the insertion sort and change the linear sort to binary lookup so that the worst time becomes theta (NLGN) (Theta (n^2)).

Solution: First thought, impossible ... After all, you need a place to move backwards ...

Yep, looking at other people's answers, it is true that even if you can find a location using a binary search, the process time complexity of the subsequent shift is still Theta (n), the overall complexity or theta (n^2).

7, please give a complexity of theta (NLGN) algorithm, given the n integer set S and another integer x, the algorithm can determine whether there are two of its and just x elements.

Solution: Your own idea: first sort (merge sort), and then the first number from the front to find, then x minus this number of the result is to find the number, and then use two points to find the number! The total complexity is theta (NLGN).

Yep, look at the answer is true.

A moment:

Study Questions

2-1 (insert sort for decimal group in the same sort) although the worst run time for a merge sort is theta (NLGN), and the worst run time for the insertion sort is theta (n^2), the constant factor in the insert sort may make the run time shorter when n is smaller. Therefore, it is meaningful to use the insertion sort to make the recursive leaf thicker when the sub-problem is in the same order. Consider the modifications to the merge sort, which use the insert sort to sort the n/k sub-table of length k, and then use the standard merge mechanism to merge the sub-tables, where k is a specific value.

A. Proof: Insert sort worst-case scenario you can sort each n/k child table with a length of K in Theta (NK) time.

B. Indicate how these sub-tables are merged in Theta (NLG (n/k)) time in the worst case scenario.

C. Assume that the worst-case run time of the modified algorithm is theta (NK+NLG (n/k)), to make the modified algorithm and the standard merge sort have the same run time, as a function of n, with the help of the theta notation, what is the maximum value of k?

D. In practice, how should we choose K?

Solution: Finish the study questions above, feel ... With the exercises is not a dimensional! Lying trough, too challenging.

A. Prove that: the time complexity of each sub-table is theta (k^2), a total of n/k sub-table, the total time is Theta (NK).

b.n/k List 22 Merge, merge and continue to merge, the total needs of LG (N/K) layer, each layer of time complexity is theta (n), so the merging total need theta (NLG) time.

C. The time complexity of the standard merge sort is theta (NLGN), which requires Theta (NLGN) =theta (NK+NLG (n/k)), when the maximum value of K can only be K=theta (LGN).

The selection criteria for D.K is a child of length k, and the insertion sort is faster than the merge sort. Well, it seems irresponsible to say so ... (We need to use paper to calculate this)

There is a possible answer on the Internet: This is an experimental problem, you should test the possible k within the legal range of K, use T-insertion-sort (k) to denote the insertion sort time for k elements, and T-merge-sort (k) to indicate the merge sort time for k elements. The problem is equivalent to the test solution of the K value with the smallest t-insertion-sort (k)/t-merge-sort (k) ratio.

The following passage is from: http://blog.kingsamchen.com/archives/715

The order value of K can not be greater than θ (LOGN), and this boundary can ensure that the progressive time of the interpolation optimization is not slower than the original merge sort.

Because of the growth characteristic of logarithmic function, the actual value of k is usually between 10~20.

Using insert sorting in a merge not only reduces the number of recursion times, but also reduces the number of memory allocations (for the original version).

PS. Need to compare and verify.

2-2 (the correctness of bubble sort) bubble sorting is a popular but inefficient sorting algorithm that is used to repeatedly exchange adjacent unordered elements.

Bubble sort Pseudo-code
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. Assume that a ' is the output of Bubblesort (a). In order to prove that Bubblesort is correct, we must prove that it will terminate and have:

A ' [1] <= a ' [2]...<= a ' [n]                                                           (2.3)

Which n=a.length. In order to prove that Bubblesort has indeed completed the sequencing, what else do we need to prove? The following two parts will prove the inequality (2.3).

B. For the second layer of the For loop to accurately describe a cyclic invariant, and prove that the loop is invariant. Your proof should use the loop invariant structure given in this chapter.

C. Using the termination conditions of the cyclic invariant (b), which describes a cyclic invariant for the first layer, this invariant can prove the expression (2.3). The structure of the cyclic invariant proofs given in this chapter should be used in the proof.

D. What is the worst-case run time for bubble sequencing? How does the performance compare to the run time of the insert sort?

Solution:

B. The second loop causes the smallest of the unsorted arrays to be moved to the front.

Initial:    J=n, sub-array is a[j-1. N]=a[n-1. N] has two elements. Within the loop, through conditional exchange statements, you can guarantee that a[n-1] < A[n] is established. So a[j-1] is a[j-1. The smallest element in n]. Hold:    A[j] is a[j at the beginning of each iteration. The smallest element in n].    in an iterative operation, when A[j] < A[j-1] are exchanged, there is always a[j-1] < a[j].    after the completion of this iterative operation, A[j-1] must be a[j-1. The smallest element in n]. Termination:    j=i+1 when exiting, so at the end, A[i] must be a[i. The smallest element in n]. http://blog.csdn.net/cppgp/article/details/7161701

C. The first loop makes it possible to continuously increase the array elements that are already sorted, knowing that they are all lined up.

Initial:    I=1, is the first element in a, so after the internal loop is complete, you can guarantee that the smallest element of A[1..N] is saved in a[1]. Hold: The    inner loop is executed each time I increment I, so the a[i is saved in A[i]. The smallest element in n].    after each internal cycle is complete, there are a[1]≤a[2]≤ ... ≤a[i] Termination:    I=length[a], at this time there are a[1]≤a[2]≤ ... ≤a[n]. Transferred from: http://blog.csdn.net/cppgp/article/details/7161701

D. The worst run time for two is Theta (n^2), but in the insertion sort the best time can be theta (n), and the bubbling sort is always theta (n^2).

2-3 (Horner) The correctness of the rules) given coefficients a0,a1,a2,..., values of an and X, code snippets

y = 0for i = n downto 0    y = ai + xy

Implements a polynomial for evaluation

The Horner rule.

PS. In China, this algorithm is called the Qin Jiushao algorithm.

A. With the theta notation, what is the elapsed time of the above code fragment that implements Horner's rules?

B. Write pseudo-code to implement a naïve polynomial evaluation algorithm, which computes each item of a polynomial from the beginning. What is the running time of the algorithm? How does the Horner rule compare to its performance?

C. Consider the following cyclic invariant:

At the beginning of each iteration of the 第2-3 line for loop, there is

The sum of the non-items is interpreted as equal to 0. In accordance with the structure of the cyclic invariant proof in this chapter, the cyclic invariant is used to prove the termination

D. Finally prove that the code snippet given above will correctly seek the polynomial depicted by the coefficient a0,a1,a2,a3...,an.

Solution: Ah ah ah, polynomial evaluation of the problem, the original is a new way of writing a rule, Horner rules.

A. This should be theta (n) ... It is obvious that n-Times polynomial uses n-times addition, n-times multiplication.

B. The pseudo-code is as follows:

Polynomial general solution pseudo Code y = 0for i = 1 to n    base = 1 for    j = 1 to i         base = base*x    y = y + Ai*basey = y + A0return y

The complexity of the above pseudo-code is theta (n^2) (1+2+3+...+n), obviously Horner's rule is much better than the general algorithm, Horner algorithm is theta (n) Ah, then the question comes: Horner algorithm save which part of the operation? Can it be simplified?

Think about it, the general algorithm repeated calculation of a good number of X's powers, each time the powers need to be recalculated, and Horner's algorithm by changing the order of calculation, the success of the problem avoided (trick where? Not yet to understand). I think of a way, the general algorithm every time the results saved up and used! This complexity is also theta (n), but there is also the problem of storage, pseudo-code:

Polynomial improved pseudo-code y = 0arr[n+1]arr[0] = 1for i = 1 to n     arr[i] = a[i-1]*x    y = y + ai * arr[i]y = y + A0return y

C. The description of the topic is right and verified, except that the first step encountered-1 times, the feeling is more ingenious, using cyclic invariant can be proved.

Initial: I=n,y[n] = 0, at the beginning of the iteration, after the loop has y[n] = A[n]. Hold: For any 0≤i≤n, after the loop: y[i] = A[i] + y[i+1] * x = a[i] + (a[i+1] * x + a[i+2] * x + ... + a[n] * x^ (n (i+1))) * x = A[i] + a[i+1] * x + a[i+2] * x^2 + ... + a[n] * x^ (n-i) Termination: I less than 0 o'clock termination, at this time there is y[0] = a[0] + a[1] * x + a[2] * x^2 + a[n] * x^n proof and y =σa[k+i+1] * x^k relationship: K from 0 to N (i+1), equivalent to 0≤k≤n-(i+1). So y =σa[k+i+1] * x^k = a[i+1] + a[i+2] * x + ... + a[n-(i+1) +i+1] * x^ (n-i) = a[i+1] + a[i        +2] * x + ... + a[n] * x^ (N-I) because the values before the i+1 loop and before the I loop are equal, with Y ' [i] representing the value before the I loop, there is: Y ' [i] = y[i+1] Horner The result of regular cyclic invariant is that:  Y[i] = A[i] + a[i+1] * x + a[i+2] * x^2 + ... + a[n] * x^ (n-i) so there are: Y ' [i] = y[i+1] = a[i+1] + a[i+2] * x + ... +                A[n] * x^ (n (i+1)) Order k=n-(i+1), then n=k+i+1, so: Y ' [i] = a[i+1] + a[i+2] * x + ... + a[k+i+1] * x^ (k+i+1-(i+1)) = A[i+1] + a[i+2] * x + ... + a[k+i+1] * x^k with Y for y ' [i], then: y = a[i+1] + a[i+2] * x + ... + a[k+i+1] * X^k =σa[k+I+1] * X^k where K is from 0 to N (i+1) proof. Transferred from: http://blog.csdn.net/cppgp/article/details/7161701

The above proofs are meticulous, thanks again.

D. This step writes the cyclic invariant to 0, which has been proved in C, in the second proof.

2-4 (reverse pair) assumes that A[1..N] is an array with n different numbers. If I < J and A[i] > A[j], then dual (I,J) is called an inverse pair (inversion) of a.

A. List the 5 reverse pairs of array <2,3,8,6,1>.

B. What array with the elements in the collection {,..., n} has the most inverse pairs? How many reverse pairs does it have?

C. What is the relationship between the run time of the insert sort and the number of reverse pairs in the input array? To prove your answer.

D. Give an algorithm that determines the number of inverse pairs in any permutation of n elements, with the worst case requiring theta (NLGN) time. (Hint: Modify merge Sort)

Solution

A. Plainly, the front is larger than the back, then there is (1,5), (2,5), (3,4), (3,5), (4,5).

B. Ah ah ah, all out of the way, let me answer this question!

Haha, do you remember the high algebra inside the matrix by row or column expansion, the sign of each item how to decide? --by the way--1 of this element (the row + the column) the second side! It doesn't seem to have anything to do with this problem, huh? But the following one is very related: In the modern algebra, learning to swap groups when exposed to this aspect of the content, OK, I forgot what piece of content, I look up or ask someone else.

So this topic, it is obvious that the array in reverse order when the number of the most ~ ~ ~ most of the number, that is, from right to left 1+2+3...+n-1=n (n-1)/2 pairs.

C. This question uses inductive method to think about, there is no reverse order of time is n, the reverse row is n^2, then the middle? Ah, is this, the number of moves do not consider, as long as the number of times to consider the comparison can be, the more the comparison, the more mobile, the comparison of the number of times decided to insert the sort of running time, and the reason for the comparison is reversed, so for the already ranked A[1..n-1], A[n] than a[1. N-1] The number of small is the number of comparisons (in fact, it should be the number of comparisons-1), so from the first number to think, the total number of reverse order is to be compared to the total number.

D. Think for a while, due to merge a total of LGN layer, then each layer to reverse the complexity of the order is n, from the Internet to see a few answers, as if not a few good writing, found a good, say an idea. To join the left and right two sub-arrays have been sorted, then as long as the right array to choose one, then the left in the array of the remaining portion of the corresponding is larger than the right one, then the corresponding reverse of the left side of the remaining elements of the number of so many. PS. In this issue, before the subsequence is merged, the inverse pairs of each of the rows in its own array are already calculated in the previous step, and the merging process is in order to find the number of inverse pairs between the subsequence.

Inversions = 0  //global variable
Count-inversions (A,p,r)
If p < r    q = (p + r)/2    count-inversions (a,p,r)
    Count-inversions (A,p,r)
    Merge-inversions (A,p,q,r)
Merge-inversions (a,p,q,r) n1 = q-p + 1n2 = R-qlet l[1:: N1 + 1]? and r[1. n2 + 1]? is new arraysfor i = 1 to N1    l[i]? = a[p + i-1]?for j = 1 to n2 r[j    ]? = A[q + j]? L[N1 + 1] =∞r[n2 + 1]? =∞i = 1j = 1for k = p to r    if L[i]?> r[j]?        A[K]? = R[i]
        Inversiongs = inversiongs + n1–i + 1?        i = i + 1    else a[k?] = r[j]?        j = j + 1

The thought turns from: http://www.cnblogs.com/lilith/archive/2012/11/21/2780319.html, has made the change oneself. The above algorithm also requires program validation, this is the next step of the work, the next step is to implement the pseudo-code mentioned above. This one is too long to write.

"Introduction to Algorithms" Reading notes--1th, 2 chapter after class (turn)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.