



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
Material Type: Assignment; Class: Data Struct & Algorithms; Subject: Computer Science; University: University of San Francisco (CA); Term: Spring 2005;
Typology: Assignments
1 / 5
This page cannot be seen from the preview
Don't miss anything!
1.5 Define an ADT for a set of integers (remember that a set may not contain duplicates). Your ADT should consist of the functions that can be performed on the sets, with each function defined in terms of its input and output. Here are some possible operations.
(a) Insert. Input: a set A and an integer n. Output: the set A ∪ {n}. (b) Delete. Input: a set A and an integer n. Output: the set A − {n}, if n ∈ A, and the set A together with a message to the effect that n isn’t in A, if n 6 ∈ A. (c) Member. Input: a set A and an integer n. Output: true if n ∈ A, and false otherwise. (d) Union. Input: two sets A and B. Output: their union A ∪ B. Note that implementing this may involve searching for duplicates. (e) Intersection. Input: two sets A and B. Output: their intersection A ∩ B. (f) Set difference. Input: two sets A and B. Output: their difference A − B. That is, the output is {a ∈ A : a 6 ∈ B}.
Note that in an object-oriented setting (e.g., Java), the set (or one of the sets in the case of union, intersection, and set difference) will probably be an implicit input, since the operation will most likely be a method on a set object.
1.13 A common problem for compilers and text editors is to determine if the parentheses (or other brackets) in a string are balanced and properly nested. For example, the string ”((())())()” contains properly nested pairs of parentheses, but the string ”)()(” does not; and the string ”())” does not contain properly matching parentheses.
(a) Give an algorithm that returns true if a string contains properly nested and balanced parentheses, and false otherwise. Hint: At no time while scanning a legal string from left to right will you have encountered more right parentheses than left parentheses.
The algorithm should scan the string from left to right, keeping track of the number of unmatched left parentheses. If, at any time, the number is negative, there’s an unmatched right parenthesis and the algorithm can terminate with an error message. If, after the entire string has been scanned, the number of unmatched left parentheses is positive, there’s an unmatched left parenthesis and the algorithm should terminate with an error. If, after the entire string has been scanned, the number is 0, the string is OK. See Parens.java on the class website for details.
3.3 Arrange the following expressions by growth rate from slowest to fastest.
4 n^2 log 3 (n) 3 n^20 n 2 log 2 (n) n (^23)
Where does n! fit into this ordering?
2 < log 3 (n) ≤ log 2 (n) < n (^23) < 20 n < 4 n^2 < 3 n. You can directly calculate that 6! = 720, 36 = 729, 7! = 5040, and 3^7 = 2187. So for n ≥ 7 , n! > 3 n.
3.4 (a) Suppose that a particular algorithm has time complexity T (n) = 3· 2 n, and that executing an implementation of it on a particular machine takes T seconds for n inputs. Now suppose that we are presented with a machine that is 64 times as fast. How many inputs could we process on the new machine in T seconds? (b) Suppose that another algorithm has time complexity T (n) = n^2 , and that executing an implementation of it on a particular machine takes T seconds for n inputs. Now suppose that we are presented with a machine that is 64 times as fast. How many inputs could we process on the new machine in T seconds? (c) Suppose that a third algorithm has time complexity T (n) = 8n, and that executing an implementation of it on a particular machine takes T seconds for n inputs. Now suppose that we are presented with a machine that is 64 times as fast. How many inputs could we process on the new machine in T seconds? The key to working these problems is observing that the runtime T tells you roughly the number of instructions executed. For example, suppose T = 1000 seconds and the old machine will execute 10^6 instructions/second. Then in T seconds, the old machine will execute 10^6 × 103 = 10^9 instructions, and the new machine will execute 64 × 109 instructions. Thus, in any given period of time the new machine will do 64 times as much work as the old machine. Hence, if Told(n) is the runtime of a program on the old machine, its runtime will be
Tnew(n) =
Told(n)
on the new machine. In the following discussion suppose that n 0 is the problem size on the old machine, and n 1 is the problem size on the new machine.
(a) We have Told(n) = 3 · 2 n, and Told(n 0 ) = T. We want to know for what value of n = n 1 will we have Tnew(n 1 ) = T. Using our formulas, we have
3 · 2 n^0 =
3 · 2 n^1.
So 64 · 2 n^0 = 2n^1 , and since 64 = 2^6 , we have 2 6+n^0 = 2n^1. Thus, n 1 = 6 + n 0. If, for example, we could previously solve a problem of size 100, we can now solve a problem of size 106.
then we’ll have cn^3 < c 2 n^3 − c 4 , for all n ≥ n 1. We know this because of the following observations. Consider the function
h(n) = c 2 n^3 − cn^3 − c 4 = (c 2 − c)n^3 − c 4.
n 1 =
( 1 + c 4 c 2
) (^13) .
Of course this may not be a whole number. So we just choose
n 0 =
⌈( 1 + c 4 c 2
) 13 ⌉ .
Note that since T (0) = −c 4 < 0 , n 1 > 0 and hence n 0 ≥ 1. Also note that since T (n) is increasing, we must have T (n 0 ) ≥ 1. Now let
c =
2 n^30
Then c > 0 and cn^30 =
2 n^30
n^30 =
< 1 = T (n 0 ).
So by our preceding observations we have
cn^3 ≤ c 2 n^3 + c 3
for all n ≥ n 0.
3.9 Determine big-Theta for the following code fragments in the average case. Assume that all variables are of type int. [We also assume that n ≥ 1. Note that for these problems the number of statements executed is the same in both the best case, worst case, and average case.]
(a) a = b+c; d = a+e;
This is two statements. Hence it’s Θ(1).
(b) sum = 0; for (i = 0; i < 3; i++) for (j = 0; j < n; j++) sum++;
The inner loop is executed n times. So it executes an+b statements for some constants a and b with a > 0. The outer loop executes 3 times. So when we add in the initialization of sum, the entire code segment will execute
c(an + b) + d
statements for some constants c and d with c > 0. Multiplying this out, we see that the number of statements executed is en + f, for some constants e and f with e > 0. We saw in class that this function is Θ(n). (c) sum = 0; for (i = 0; i < n*n; i++) sum++;
Let m = n^2. Then the number of statements executed is am + b for some constants a and b with a > 0. So this is Θ(m), and since m = n^2 , we see that this is Θ(n^2 ). (d) Assume array A contains n values. for (i = 0; i < n; i++) { for (j = 0; j < n; j++) A[i] = DSutil.random(n) // random takes constant time sort(A, n); // sort takes n log n time }
The inner loop executes an + b statements for constants a, b with a > 0. The call to sort takes time n log n. So the total number of statements executed in the body of the loop is
cn log(n) + dn + e,
for constants c, d, e with c > 0. Since the outer loop is executed n times, the total number of statements executed is f n(cn log(n) + dn + e) + g
Multiplying this out, we see that the code is Θ(n^2 log(n)).
Note that this argument can be considerably simplified by using the rules on page 56 of the text (which also apply to big-Ω and big-Θ). The inner loop is Θ(n). The sort is Θ(n log n). So the body of the outer loop is Θ(n log n) (by rule 3). Thus, by rule 4, the code is Θ(n^2 log n).