Problem Set 1

Due before the start of lecture on September 22, 2026.
See below for a summary of the policies regarding late submissions.

Preliminaries

Homework is due prior to the start of lecture. If it is submitted more than 10 minutes after the start of lecture, it will be considered a full day late. There will be a 10% deduction for late submissions that are made by 11:59 p.m. Eastern time on the Sunday after the deadline, and a 20% deduction for submissions that are made after that Sunday and before the start of the next lecture. We will not accept any homework that is more than 7 days late. Plan your time carefully, and don’t wait until the last minute to begin an assignment. Starting early will give you ample time to ask questions and obtain assistance.

In your work on this assignment, make sure to abide by our policies on academic conduct.

If you haven’t already done so, you should complete Problem Set 0 before beginning this assignment.

If you have questions while working on this assignment, please come to office hours, post them on Ed Discussion, or email cscie22-staff@lists.fas.harvard.edu


Part I: Short-answer problems

40 points total

Creating the necessary folder

  1. If you haven’t already created a folder named e22 for your work in this course, follow these instructions to do so.

  2. Then create a subfolder called ps1 within your e22 folder, and put all of the files for this assignment in that folder.

Creating the necessary file

The problems from Part I will all be completed in a single PDF file. To create it, you should do the following:

  1. Access the template that we have created by clicking on this link and signing into your Google account as needed.

  2. When asked, click on the Make a copy button, which will save a copy of the template file to your Google Drive.

  3. Select File->Rename, and change the name of the file to ps1_partI.

  4. Add your work for the problems from Part I to this file.

  5. Once you have completed all of these problems, choose File->Download->PDF document, and save the PDF file in your ps1 folder. The resulting PDF file (ps1_partI.pdf) is the one that you will submit. See the submission guidelines at the end of Part I.

Problem 1 Memory management and arrays

8 points

Java built-in classes

In your work on this and subsequent problem sets, you should not use any of Java’s built-in collection classes (e.g., ArrayList) or utility classes (e.g., Arrays), unless a problem explicitly states that you may do so.

Consider the following lines of Java code:

int[] a = {2, 4, 6, 8, 10, 12};
int[] b = new int[6];
int[] c = new int[6];

b = a;
for (int i = 0; i < a.length; i++) {
    c[i] = a[i];
}

a[2] = c[5];
c[2]++;
System.out.println(a[2] + " " + b[2] + " " + c[2]);
  1. (6 points) In ps1_partI (see above), we have given you the beginnings of a memory diagram for these lines of code. It includes both the stack and the heap.

    On the stack, we have included a stack frame for the main method, which is where we are assume that the above lines are found. On the heap, we have included the array to which the variable a refers.

    Complete the provided memory diagram so that it shows the final result of the above lines of code.

    To do so, you should:

    • Click on the diagram and then click the Edit link that appears below the diagram.

    • Make whatever changes are needed to the diagram. Below the thick horizontal line, we have given you a set of extra components that you can use as needed by dragging them above the thick line and putting them in the correct position. You may not need all of the provided components.

    • You can also edit any of the values in an array by clicking on one of its cells and editing the text that is inside the cell.

    • Once you have made all of the necessary changes, click the Save & Close button.

  2. (2 points) Indicate what will be printed by the final line of code shown above.

Problem 2 Array practice

10 points total; 5 points each part

In this problem, you will write static methods that operate on arrays. These methods do not need to use recursion, and they do not need to be implemented as part of a class. Simply include the methods with your answers for the other problems from Part I.

  1. Write a method with the header

    public static boolean isSorted(int[] arr)
    

    that takes a reference to an array of integers and returns true if the array is sorted (i.e., if the elements are in increasing order), and false otherwise.

    Special cases:

    • If the method is passed a value of null, it should throw an IllegalArgumentException.

    • If the method is passed an array of length 0 or an array with one element, the method should return true.

    See below for a recommended approach to testing this method.

  2. Write a method with the header

    public static void scale(int[] arr, int factor)
    

    that takes a reference to an array of integers arr and an integer factor and that scales (i.e., multiplies) each element of the array arr by factor. For example, consider this array:

    int[] values = {1, 2, 4, 6, 8, 10};
    

    After calling scale(values, 3), the contents of the values array should be {3, 6, 12, 18, 24, 30}.

    Note that the method has a return type of void, which means that it should not return a value. It doesn’t need to do so, because it should be modifying the internals of the array arr, and thus those changes will still be there after the method returns.

    Special cases:

    • If the method is passed a value of null, it should throw an IllegalArgumentException.

    • If the method is passed an array with a length of 0, it should leave the array unchanged.

  3. Testing Your Methods in VSCodium We encourage you to use VSCodium to test your methods for parts 1 and 2 above. Here are the steps:

    1. If you haven’t already done so, create a folder named ps1 for your work on this assignment.

    2. Download the following file: Problem2Test.java

      Make sure to put the file in your ps1 folder. If your browser doesn’t allow you to specify where the file should be saved, try right-clicking on the link above and choosing Save as… or Save link as…, which should produce a dialog box that allows you to choose the correct folder for the file.

    3. In VSCodium, select the File->Open Folder menu option, and use the resulting dialog box to find and open the folder that you created for this assignment. (Note: You must open the folder; it is not sufficient to simply open the file.)

      The name of the folder should appear in the Explorer pane on the left-hand side of the VSCodium window, along with the name of the Problem2Test.java file that you downloaded above.

    4. Click on the name Problem2Test.java, which will open an editor window for that file.

    5. Put your methods inside the provided class. We have given you some code in the main method for testing your methods, but we encourage you to add additional tests as well.

      Note: You may use the Arrays.toString() method for testing, since it allows to easily view the contents of an array. However, you should not be using this method or any other method from the Arrays class for any purpose other than testing.

    6. Open VSCodium’s built-in Terminal pane. You can do this by pressing the Control key and the backtick key, or by selecting Terminal->New Terminal from the menu. The Terminal should open at the bottom of the VSCodium window. It should already be in the ps1 folder.

    7. Compile your program:

      1. Save the changes that you made to the file by selecting File->Save or using Ctrl-S.

      2. Type the following command in the Terminal and then press Enter:

        javac Problem2.java
        

        Doing so word will produce a list of any syntax errors in the code.

        Notes:

        • Each error message includes the line number of the code that produced the error. For example, let’s say that you see an error message that begins with the following

          Problem2.java:5: error: ...
          

          The :5 that comes after the name of the file tells you that the error is on line 5 of the file.

        • If you press the Ctrl key as you click on the line number in an error message, the corresponding line of code should be highlighted in the editor window.

    8. Continue editing the code and recompiling until javac does not report any errors. Important: Make sure to save any changes that you make before you try to recompile!

    9. Run the program: Once all of the syntax errors have been fixed, enter the following command from the Terminal:

      java Problem2
      
    10. Make sure that the tests produce the expected results, and edit your methods as needed.

Once you are happy with your methods, put them in your ps1_partI file. Do not submit the Problem2Test.java file.

Problem 3 Recursion and the runtime stack

12 points

Consider the following recursive method:

public static int mystery(int a, int b) {
    if (a < 0) {
        return 1;
    } else {
        int myst_rest = mystery(a - b, b);
        return 2 + myst_rest;
    }
}
  1. (5 points) Trace the execution of mystery(20, 6). To do so, complete the template that we have provided in section 3-1 of ps1_partI. In particular, you should:

    • Include a separate “frame” for each call. We have filled in some of the components of the frames for the first two calls for you. You should replace each ... with the appropriate integer, and you should add frames for additional calls as needed, until you reach the base case.

    • Begin each frame with lines that explicitly state the values assigned to the parameters, as we have done for the first call.

    • Next, if the call is a base case, you can simply show the value that is returned (omitting the line for myst_rest). If the call is a recursive case, you should show the recursive call on the line for myst_rest.

    • Once you have reached the base case, you should work your way back through the frames for the previous calls. Add in both the results of the recursive call (i.e, the value assigned to myst_rest) and the value returned by the call itself.

  2. (2 points) What is the value returned by mystery(20, 6)?

  3. (2 points) During the execution of mystery(20, 6), method frames are added and then removed from the stack. How many method frames are on the stack when the base case is reached? You should assume that the initial call to mystery(20, 6) is made from within the main() method, and you should include the stack frame for main in your count.

  4. (3 points) Are there any initial values of the parameters a and b that would produce infinite recursion? Explain briefly why or why not.

Problem 4 Rewriting a method

10 points

Consider the following method, which uses iteration (a for loop) to search for an item in an array of integers. The method returns true if the item is found in the array, and false if it is not.

public static boolean search(int item, int[] arr) {
    for (int i = 0; i< arr.length; i++) {
        if (arr[i] == item) {
            return true;
        }
    }

    return false;
}
  1. (4 points) Rewrite this method so that it searches for an item in an array that can contain any type of object. Change the types of the parameters accordingly, and make whatever changes are needed to the body of the method.

  2. (6 points) Rewrite your answer to part 1 so that it uses recursion instead of iteration. You will need to add a third parameter (call it start) that keeps track of where you are in the array. More precisely, start will specify the position in the array where the search for item should begin. For example, search("hello", arr, 0) should search for “hello” in the full array (beginning at position 0), whereas search("hello", arr, 2) should search for "hello" in the subarray that begins at position 2 and goes to the end of the array.


Submitting your work for Part I

Submit your ps1_partI.pdf file by taking the following steps:

  1. If you still need to create a PDF file, open your file on Google Drive, choose File->Download->PDF document, and save the PDF file on your machine.

  2. Click on the name of the assignment in the list of assignments on Gradescope. You should see a pop-up window labeled Submit Assignment. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)

  3. Choose the Submit PDF option, and then click the Select PDF button and find the PDF file that you created. Then click the Upload PDF button.

  4. You should see a question outline along with thumbnails of the pages from your uploaded PDF. For each question in the outline:

    • Click the title of the question.
    • Click the page(s) on which your work for that question can be found.

    As you do so, click on the magnifying glass icon for each page and doublecheck that the pages that you see contain the work that you want us to grade.

  5. Once you have assigned pages to all of the problems in the question outline, click the Submit button in the lower-right corner of the window. You should see a box saying that your submission was successful.

Important

  • It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.

  • If you are unable to access Gradescope and there is enough time to do so, wait an hour or two and then try again. If you are unable to submit and it is close to the deadline, email your homework before the deadline to cscie22-staff@lists.fas.harvard.edu


Part II: Programming problems

60-70 points total

Problem 5 Adding methods to the ArrayBag class

25 points total

Getting started

  1. If you haven’t already done so, create a folder named ps1 for your work on this assignment.

  2. Download the following file:
    ArrayBag.java

    Make sure to put the file in your ps1 folder. If your browser doesn’t allow you to specify where the file should be saved, try right-clicking on the link above and choosing Save as… or Save link as…, which should produce a dialog box that allows you to choose the correct folder for the file.

  3. In VSCodium, select the File->Open Folder menu option, and use the resulting dialog box to find and open the folder that you created for this assignment. (Note: You must open the folder; it is not sufficient to simply open the file.)

    The name of the folder should appear in the Explorer pane on the left-hand side of the VSCodium window, along with the name of the ArrayBag.java file that you downloaded above.

  4. Click on the name ArrayBag.java, which will open an editor window for that file.

  5. In ArrayBag.java, add the methods described below to the ArrayBag class, and then add code to the main() method to test these methods. You should not add any new fields to the class.

  6. In the Terminal, use javac to compile your code and java to run it, taking steps similar to the ones described at the end of Problem 2.

    We strongly recommend compiling and testing each new method as you add it, fixing any issues with one method before moving on to the next one.

Here are the methods you should add:

  1. public int roomLeft()
    This method should return the number of additional items that the called ArrayBag has room to store. For example, if the maximum size of the bag is 10 and there are currently 7 items in the bag, this method should return 3, since the bag has room for 3 more items. Hint: This method should only need one or two lines of code.

  2. public boolean isEmpty()
    This method should return true if the called ArrayBag is empty, and false otherwise.

  3. public void increaseCapacity(int amount)
    This method should increase the maximum capacity of the called ArrayBag by the specified amount. For example, if b has a maximum capacity of 10, then b.increaseCapacity(5) should give b a maximum capacity of 15. As part of your implementation, you will need to create a new array with room to support the new maximum capacity, copy any existing items into that array, and replace the original array with the new one by storing its reference in the called object.

    Special cases:

    • If the parameter is 0, the method should just return without making any changes to the called object.

    • If the parameter is negative, the method should throw an IllegalArgumentException. See our second ArrayBag constructor for an example of throwing an exception.

  4. public boolean addItems(ArrayBag other)
    This method should attempt to add to the called ArrayBag all of the items found in the parameter other. If there is currently room for all of the items to be added, the items should be added and the method should return true. If there isn’t enough room for all of the items to be added, none of them should be added and the method should return false.

    Hints:

    • Don’t forget that your addItems method has direct access to the private fields of the ArrayBag passed in for other. See our containsAll method for another example of an ArrayBag method that takes another ArrayBag object as a parameter.

    • You can simplify your implementation of this method if you have it call one or more of the existing methods of the ArrayBag class. Here again, the existing containsAll method provides a relevant example.

    Special cases:

    • The method should return true if the bag represented by other is empty.
    • If the parameter is null, the method should throw an IllegalArgumentException. See our second ArrayBag constructor for an example of throwing an exception.
  5. public ArrayBag intersectionWith(ArrayBag other)
    This method should create and return an ArrayBag containing one occurrence of any item that is found in both the called object and the parameter other. For full credit, the resulting bag should not include any duplicates. For example, if b1 represents the bag {2, 2, 3, 5, 7, 7, 7, 8} and b2 represents the bag {2, 3, 4, 5, 5, 6, 7}, then b1.intersectionWith(b2) should return an ArrayBag representing the bag {2, 3, 5, 7}. Give the new ArrayBag a maximum size that is equal to the number of items in the bag with the smaller number of items (but see below for an exception).

    The hints for the previous method also apply here.

    Special cases:

    • If there are no items that occur in both bags—including cases in which one or both of the bags are empty—the method should return an empty ArrayBag.

    • If the parameter is null, the method should throw an IllegalArgumentException.

    • In general, the returned ArrayBag should have a maximum size that is equal to the number of items in the bag with the smaller number of items. However, because it’s not possible to construct an ArrayBag with a maximum size of 0, you should give the new ArrayBag a maximum size of 1 if one or both of the original bags are empty.

Problem 6 Writing recursive methods

35 points total

Getting started

  1. In VSCodium, select the File->Open Folder menu option, and use the resulting dialog box to find and open your ps1 folder. The name of the folder should appear in a new Explorer pane on the left-hand side of the VSCodium window.

  2. Select File->New Text File, which will open up an empty window known as an editor window for your new program. It will initially have a name that is something like Untitled-1.

  3. Select File->Save, and give the file the following name:

    Problem6.java
    

    Important: When naming a Java file, the case of the letters matters. Make sure to use the exact combination of upper-case and lower-case letters that we have specified.

  4. In your Problem6.java file, create a class named Problem6, implement the methods described below within that class, and then create a main() method to test these methods.

  5. In the Terminal, use javac to compile your code and java to run it, taking steps similar to the ones described at the end of Problem 2.

    Here again, we recommend compiling and testing each new method before moving on to the next one.

Requirements

  1. The methods that you write must be purely recursive. The use of iteration (i.e., for, while, or do-while loops) is not allowed.
  2. The only built-in String methods that you may use are charAt, length, equals, and substring. No use of other String methods is allowed. In addition, make sure to follow any additional restrictions specified in the problem.
  3. Do not use any global variables — i.e., variables that are declared outside of a method.
  4. Use the headers specified for the methods without changing them in any way.
  5. Limit yourself to writing the methods specified below. Do not write any additional “helper” methods that assist the required methods; rather, the methods listed below should provide all of their required functionality by themselves.

Here are the methods:

  1. public static int sumSquares(int[] vals, int start)

    This method should take an array vals of 1 or more integers and a non-negative integer start. If start is a valid index for vals, the method should return the sum of the squares of the integers in the portion of vals that begins with position start.

    For example, given the following array of integers:

    int[] arr = {2, 5, 3, 4};
    
    • sumSquares(arr, 0) should return 54, which is the result of the computation 2*2 + 5*5 + 3*3 + 4*4.
    • sumSquares(arr, 2) should return 25 (the result of the computation 3*3 + 4*4), since 25 is the sum of the squares of the values in the subarray {3, 4} – i.e., the portion of the array arr that begins at position 2.

    If start is greater than or equal to the length of the array, the method should return 0.

    You may assume that vals is non-null and that it refers to an array containing at least 1 value, and that start is a non-negative integer.

  2. public static void printReverse(String s)
    This method should use recursion to print the individual characters in the string s in reverse order. For example, printReverse("Harvard") should print

    dravraH
    

    The method should not return a value.

    Special cases: If the parameter is null or the empty string (""), the method should not print anything. It should simply return.

  3. public static String reflect(String s)
    This method should take a string s and use recursion to create and return a “reflected” version of the string in which the original string is followed by the characters of the string in reverse order. For example:

    • reflect("method") should return "methoddohtem"
    • reflect("abc") should return "abccba"

    This method should not do any printing; it should return the appropriate string.

    Special cases: If the value null or the empty string ("") are passed in as the parameter, the method should just return an empty string.

  4. public static boolean contains(String s, char c)
    This method should take an arbitrary string s and a single character c, and it should use recursion to determine is the string s contains the character c. It should return true if s does contain c, and it should return false if it does not. For example:

    • contains("hello", 'e') should return true
    • contains("hello", 'l') should return true
    • contains("hello", 'x') should return false
    • contains("", 'x') should return false

    You may assume that both parameters are valid and non-null.

    Hint: You will need at least two base cases.

  5. public static int numDiff(String s1, String s2)
    This method should take two strings s1 and s2 and use recursion to determine and return the number of differences between the two strings – i.e., the number of positions at which the two strings have different characters. If one string is longer than the other, all of its extra characters should count as differences. For example:

    • numDiff("alien", "allen") should return 1 because the strings only differ in one position (position 2).
    • numDiff("alien", "alone") should return 3 because the the characters in the last 3 positions of the strings are all different.
    • numDiff("same", "same") should return 0 because there are no differences between the two strings!
    • numDiff("same", "sameness") should return 4 because although the first 4 positions of the strings are the same, the second string has an extra 4 characters.
    • numDiff("some", "sameness") should return 5 because the strings differ in position 1 and the second string also has an extra 4 characters.
    • numDiff("", "abc") and numDiff("abc", "") should both return 3 because one of the strings is empty and thus all of characters in the other string are extra characters.

    You may assume that neither parameter is null.

  6. public static String bwOr(String b1, String b2)

    This method should take two bitstrings b1 and b2 – i.e., two strings composed of 0 or more 0s or 1s – and it should use recursion to create and return a string that represents the bitwise OR of the binary numbers represented by those bitstrings.

    In lecture, we discussed the bitwise AND of two binary numbers. The bitwise OR of two binary numbers is performed in a similar way, but:

    • corresponding pairs of bits are ORed togther
    • if one number has more bits than the other, its extra bits are effectively ORed with 0s, and thus they appear unchanged in the result.

    For example, bwOr("10101010", "11000") should return "10111010", because taking the bitwise OR of the corresponding binary numbers on paper would look like this:

    10101010
       11000
    --------
    10111010
    

    Note that a given column produces a 1 if either or both of the corresponding bits is a 1, because the OR of two boolean values is true if one or both of the boolean values are true. In addition, all of the extra bits from the longer number end up appearing unchanged in the final result.

    Here are some other examples:

    • bwOr("10100", "00101") should return "10101"
    • bwOr("10100", "1000101") should return "1010101"
    • bwOr("10111", "") should return "10111"
    • bwOr("", "0110") should return "0110"

    You may assume that neither parameter is null.

    Hint: The bwAnd method that we wrote together in lecture provides a good starting point for this method. However, you many find it helpful for your bwOr method to have more than one base case.

  7. public static int indexOf(char c, String s)
    This method should use recursion to find and return the index of the first occurrence of the character c in the string s, or -1 if c does not occur in s. For example:

    • indexOf('b', "rabbit") should return 2
    • indexOf('x', "rabbit") should return -1

    The method should return -1 if the value null or the empty string ("") is passed in as the second parameter.

    The String class comes with a built-in indexOf() method; you may not use that method in your solution!

Problem 7 Extra practice with recursion

10 points; required for grad-credit students; “partial” extra credit for others

Take steps similar to the ones outlined in the previous problem to create a file named Problem7.java. Then create a class named Problem7 that contains the methods described below, as well as a main() method that tests those methods.

Important: The requirements from the previous problem also apply here.

  1. public static int nthIndexOf(int n, char c, String s)
    This method should use recursion to find and return the index of the nth occurrence of the character c in the string s, or -1 if there are fewer than n occurrences of c in s. For example:

    • nthIndexOf(1, 'a', "banana") should return 1, because the first occurrence of 'a' in "banana" has an index of 1.
    • nthIndexOf(2, 'a', "banana") should return 3, because the second occurrence of 'a' in "banana" has an index of 3.
    • nthIndexOf(3, 'a', "banana") should return 5, because the third occurrence of 'a' in "banana" has an index of 5.
    • nthIndexOf(4, 'a', "banana") should return -1, because there are fewer than four occurrences of 'a' in "banana".

    The method should return -1 if the value null or the empty string ("") is passed in as the third parameter, or if the first parameter is less than or equal to 0.

  2. public static String trim(String s)
    This method should take a string s and use recursion to return a string in which any leading and/or trailing spaces in the original string are removed. For example:

    trim("  hello world ")
    

    should return the string "hello world", and

    trim("recursion     ")
    

    should return the string "recursion".

    The String class comes with a built-in trim() method that does the same thing as the method that we’re asking you to write; you may not use that method in your solution!

    Special cases:

    • If the parameter is null, the method should return null.

    • If the parameter is the empty string, the method should return the empty string.


Submitting your work for Part II

You should submit the following files:

  • ArrayBag.java
  • Problem6.java
  • Problem7.java (if you worked on that problem)

Here are the steps:

  1. Click on the name of the assignment in the list of assignments. You should see a pop-up window with a box labeled DRAG & DROP. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)

  2. Add all three files to the box labeled DRAG & DROP. You can either drag and drop the files from their folder into the box, or you can click on the box itself and browse for the files.

  3. Click the Upload button.

  4. You should see a box saying that your submission was successful. Click the (x) button to close that box.

  5. The Autograder will perform some tests on your file. Once it is done, check the results to ensure that the tests were passed. If one or more of the tests did not pass, the name of that test will be in red, and there should be a message describing the failure. Based on those messages, make any necessary changes. Feel free to ask a staff member for help.

    Note: You will not see a complete Autograder score when you submit. That is because additional tests will be run later, after the final deadline for the submission has passed. For such problems, it is important to realize that passing all of the initial tests does not necessarily mean that you will ultimately get full credit on the problem. You should always run your own tests to convince yourself that the logic of your solutions is correct.

  6. If needed, use the Resubmit button at the bottom of the page to resubmit your work. Important: Every time that you make a submission, you should submit all of the files for that Gradescope assignment, even if some of them have not changed since your last submission.

  7. Near the top of the page, click on the box labeled Code. Then click on the name of each file to view its contents. Check to make sure that you see the code that you want us to grade.

Important

  • It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.

  • If you are unable to access Gradescope and there is enough time to do so, wait an hour or two and then try again. If you are unable to submit and it is close to the deadline, email your homework before the deadline to cscie22-staff@lists.fas.harvard.edu