Skip to main content

Assignment 6: Complexity analysis

Assigned
Friday, 15 March 2019
Due
Thursday, 4 April 2019
Summary
To get some practice (a) solving small algorithmic problems and (b) analyzing the complexity of solutions to these problems, you’ll solve a handful of these problems in Java.
Collaboration
Each student should turn in his, her, zir, or their own solutions. Students should feel free to support each other, provided they cite any help they’ve received.
Submitting
Share your GitHub repo with csc207-grader. Then send an email to csc207-01-grader@grinnell.edu with the address of your repository. The subject of your email should be [CSC207-01] Assignment 6 and should contain your answers to all parts of the assignment.

In addition to placing your code in a private GitHub repository, you should also include a README.md file as well as a write-up of the complexity analyses and questions described in each problem in a file called writeup.txt.

Problem 1: Contains

Write a static method contains that takes three parameters—an array of doubles dubs, a double value eps, and a double d—and returns true if there is a element dubs[i] in the array such that abs(dubs[i] - d) < eps.

Once you have written the contains method, analyze its worst-case complexity. Choose an appropriate set of operations to count, define the input of your model, describe what the worst-case scenario is for this method, and give a model T of the time complexity of your method. Finally, summarize the model with a tight upper bound characterization of T using Big-O notation, proving (by giving an appropriate c and x_0) that the upper bound is sound.

Problem 2: Fast exponentiation

Write a method fastModExp that takes three integers, x, y, and m and returns xy mod m. Your method should take advantage of two important identities.

  • xy mod m = (x2 mod m)(y/2) mod m when y is even.
  • xy mod m = (x * (x(y-1) mod m)) mod m when y is odd.

Once you have written the fastModExp method, analyze its complexity, assuming that the input y is a power of two. Choose an appropriate set of operations to count, define the input of your model and give a model T as a recurrence relation of the time complexity of your method. Solve your recurrence relation using the substitution method described in class to obtain an explicit formula for the time complexity. Finally, summarize the model with a tight upper bound characterization of T using Big-O notation, proving (by giving an appropriate c and x0) that the upper bound is sound.

(Hint: your complexity model should not be linear!)

Problem 3: All pairs

With the following class definition for a Pair class (defined in Pair.java):

// In IntPair.java
public class IntPair {
  private int fst;
  private int snd;
  public IntPair(int fst, int snd) {
    this.fst = fst;
    this.snd = snd;
  } // IntPair(int,int)

  public int getFst() { 
    return fst; 
  } // getFst()

  public int getSnd() { 
    return snd; 
  } // getSnd()
} // IntPair

Write a static method in your Program class called allPairs that takes an integer array and returns all possible pairs of elements from the input array in a new array (of type Pair array). The set of possible pairs includes pairing each element with itself. For example, if the input array arr has the form { 3, 5, 9 }, then allPairs(arr) returns the array { (3, 3), (3, 5), (3, 9), (5, 3), (5, 5), (5, 9), (9, 3), (9, 5), (9, 9) } (although not necessarily in that order). If the null array is passed to allPairs, then an IllegalArgumentException should be thrown.

Once you have written the allPairs method, analyze its complexity. Choose an appropriate set of operations to count, define the input of your model, and give a model T of the time complexity of your method. Finally, summarize the model with a tight upper bound characterization of T using Big-O notation, proving (by giving an appropriate c and x0) that the upper bound is sound.

Problem 4: Concat-replicate

Write a static method called concatAndReplicateAll that takes an array of strings and an integer n and returns a single string that is the result of replicating them all n times and then concatenating them all together. For example, if the input array arr has the form { "hello", "world", "!" } and n = 3 then concatAndAreplicateAll(arr) returns the string "hellohellohelloworldworldworld!!!" If the null array is passed to concatAndReplicateAll, then an IllegalArgumentException should be thrown.

Once you have written the concatAndReplicateAll method, analyze its complexity informally. Choose an appropriate set of operations to count, define the input of your model, give a tight upper bound characterization of the method’s time complexity using Big-O notation, and in a sentence, justify your choice of bound.

Finally, does your analysis change if I tell you that Java string concatenation of two strings of lengths n and m is O(n+m)? This is because strings are immutable, so that building the resulting string consists of traversing both strings rather than simply appending the second string onto the first. State how your runtime changes as a result of this new information.

Problem 5: Interleave

Write a static method called interleave that takes two arrays of integers and returns a third array that is the result of interleaving the first array with the second. For example, if the input arrays arr1 and arr2 have values {0, 1, 2} and {3, 4, 5}, respectively, then interleave(arr1, arr2) produces the new array {0, 3, 1, 4, 2, 5}. If one array is longer than the other, then the remains of the longer array are simply placed at the end of the output array after interleaving. For example, if arr2 above was {3, 4, 5, 6, 7, 8} then interleave(arr1, arr2) produces {0, 3, 1, 4, 2, 5, 6, 7, 8}.

Once you have written the interleave method, analyze its time complexity informally. Choose an appropriate set of operations to count, define the input of your model, give a tight upper bound characterization of the method’s time complexity using Big-O notation, and in a sentence, justify your choice of bound.

Next, analyze the interleave method’s space complexity informally. Recall that the space complexity of a function is how much memory it uses—heap allocations and stack space (for recursive functions). Give a tight upper bound characterization of the method’s space complexity using Big-O notation and in a sentence, justify your choice of bound.

Finally, review the previous problem’s functions and their space complexity. (You do not need to provide them in your write-up, but you should go back and informally analyze their space complexity). After review, what can you conclude about the relationship between time and space complexity? In other words, if we know the space complexity of a function, can we put a bound on its time complexity?

Acknowledgements

The original version of this assignment was written by Peter-Michael Osera. Samuel A. Rebelsky make some updates for Spring 2019.