due by 11:59 p.m. on Thursday, March 19, 2026
Important
Don’t forget that each of your methods should be preceded by a comment that explains what your method does and what its inputs are. In addition, you should include a comment at the top of each Java file, and you should use good programming style more generally.
In addition, you should continue to follow the other guidelines that we gave you in the prior problem sets. In particular, see here.
In your work on this assignment, make sure to abide by the collaboration policies of the course.
If you have questions while working on this assignment, please come to office hours or post them on Piazza.
Make sure to follow the instructions outlined at the end of Part I and Part II when submitting your assignment.
67 points total
Problems in Part I will be completed in a single PDF file. To create it, you should do the following:
Open the template that we have created for these problems in Google Docs: ps5_partI
Select File->Make a copy..., and save the copy to your Google
Drive using the name ps5_partI.
Add your work to this file.
Once you have completed all of these problems, choose
File->Download->PDF document, and save the PDF file on your machine.
The resulting PDF file (ps5_partI.pdf) is the one that you will
submit. See the submission guidelines at the end of Part I.
8 points; individual-only
A number of the algorithms that we consider in CS 112 involve recursive methods in which a given invocation of the method may make two or more recursive calls. To understand how this type of algorithm works, it helps to draw a call tree for a given set of initial parameters.
In this problem, you will draw such a call tree to illustrate the execution of a simple recursive method that operates on integers. You may find it helpful to review our solutions to the similar problem in Lab 7 problem before continuing.
Here is the method you will trace:
public static int foo(int x, int y) { if (y <= 0 || x <= 0 || Math.abs(x-y) >= 4) { return x+y; } else { int result1 = foo(x - 2, y + 1); int result2 = foo(x + 1, y - 2); return result1 + result2; } }
Assume that we begin with the following initial call to this method:
foo(3, 3)
Construct a call tree that shows each invocation of the method, and that uses lines to connect a given invocation to the recursive calls that it makes (if any). Follow the same format that we use in our solutions for Lab 7.
In section 1-1 of ps5_partI, we have given you an initial diagram.
You should take the following steps to complete it:
Add each subsequent call with its parameters to the call tree in the appropriate place.
If a given call is a base case, simply put its return value under
the call, as we do in our Lab 7, Task 2 solution for calls to
fib(1) and fib(0).
If a given call is not a base case, use lines composed of / or
\ characters to connect the call to the recursive call(s) that
it makes.
Precede each call with a number that indicates the overall order in which the calls were made.
Underneath your call tree, list the order in which the calls return, as well as their return values. When you refer to a given call in this part of the problem, use its number from the call tree.
For example, the initial call always returns last, so the last line in this part of the problem should look like this:
call 1 (foo(3,4)) returns ...
where you replace the ... with its return value.
See our solution for Lab 7 for another example of what this part of your solution should look like.
7 pts. total; individual-only
Express each of the following functions using Big-O notation.
Represent your answer as an equality (e.g., p(n) = O(n^2)).
a(n) = 33n+1500b(n) = 2nlog(n) + n^2 + 250nc(n) = 33n + 42n^2 +73d(n) = 5n*ne(n) = 5^nf(n) = 3nlog(n) + 15n^3 + n^2 + 10^7g(n) = 100 + 2n + 3nlog(n) + √(n)15 pts. total; individual-only
In each of the following code fragments, determine how many times the count()
method is called as a function of the variable n? Use big-O notation to express the
run-time efficiency of each method, and explain your answer briefly.
Code Fragment 1
for (int i = n; i > 0; i/=2) for (int j = 0; j < n; j++) for (int k = 0; k < 1000; k++) count();
Code Fragement 2
for (int i = 0; i < 3; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < j; k++) { count(); } } }
Code Fragment 3
for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) for (int k = 0; k < j; k++) count();
Code Fragment 4
for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { count(); } }
Code Fragment 5
for (int i = 0; i < n; i++) { for (int j = 0; j < 2*n; j++) { for (int k = n; k >= 1; k = k/2) { count(); } } }
6 points; individual-only
Suppose that you want to count the number of duplicates in an unsorted array of n elements. A duplicate is an element that appears multiple times; if a given element appears x times, x - 1 of them are considered duplicates. For example, consider the following array:
{10, 6, 2, 5, 6, 6, 8, 10, 5}
It includes four duplicates: one extra 10, two extra 6s, and one extra 5.
Below are two algorithms for counting duplicates in an array of integers:
1. Algorithm A:
public static int numDuplicatesA(int[] arr) { Sort.mergesort(arr); // we will cover mergesort on Tuesday, but it has O(nlogn) efficiency in both best and worst case int numDups = 0; for (int i = 1; i < arr.length; i++) { if (arr[i] == arr[i - 1]) { numDups++; } } return numDups; }
What is the worst-case time efficiency of algorithm A in terms of the length n of the array? Use big-O notation, and explain your answers briefly.
2. Algorithm B:
public static int numDuplicatesB(int[] arr) { int numDups = 0; for (int i = 0; i < arr.length - 1; i++) { for (int j = i + 1; j < arr.length; j++) { if (arr[j] == arr[i]) { numDups++; break; } } } return numDups; }
What is the worst-case time efficiency of algorithm B? Use big-O notation, and explain your answers briefly.
3. Algorithm C: Your turn
Suppose you known that your unsorted array of n elements contains elements in the range [0,n-1]. Write your implementation numDuplicates that also uses iteration (i.e., you should not use recursion) but that has a better time efficiency. What is the worst-case time efficiency of algorithm C? Use big-O notation, and explain your answers briefly.
6 points; 2 points for each part; individual-only
Important: When answering these questions, make sure to apply the
versions of these algorithms in the Sort class we give you. The Java
code for each algorithm can be found in our Sort
class.
Given the following array:
{10, 18, 4, 24, 33, 40, 8, 3, 12}
If the array were sorted using selection sort, what would the array look like after the third pass of the algorithm (i.e., after the second time that the algorithm performs a pass or partial pass through the elements of the array)?
If the array were sorted using insertion sort, what would the array look like after the fifth iteration of the outer loop of the algorithm?
If the array were sorted using the (non optimized) version of bubble sort presented in lecture, what would the array look like after the fourth pass of the algorithm?
Important
There will be no partial credit on the above questions, so please check your answers carefully!
7 points; individual-only
Suppose that you want to find the largest element in an unsorted array of n elements. Algorithm A searches the entire array sequentially and keeps track of the largest element seen thus far. Algorithm B sorts the array using insertion sort, and then reports the last element as the largest.
What is the big-O time efficiency of Algorithm A in the best, average, and worst cases? Explain your answer briefly. (You do not need to implement either algorithm. We just want you to analyze them.)
What is the big-O time efficiency of Algorithm B in the best, average, and worst cases? Explain your answer briefly.
Which algorithm has a more efficient run-time complexity? Explain briefly.
12 points; 2 points for each part; individual-only
Important: When answering these questions, make sure to apply the
versions of these algorithms in the Sort class we give you. The Java
code for each algorithm can be found in our Sort
class.
Given the following array:
{14, 7, 27, 13, 24, 20, 10, 33}
If the array were sorted using selection sort, what would the array look like after the second pass of the algorithm (i.e., after the second time that the algorithm performs a pass or partial pass through the elements of the array)?
If the array were sorted using insertion sort, what would the array look like after the fourth iteration of the outer loop of the algorithm?
If the array were sorted using the version of bubble sort presented in lecture, what would the array look like after the third pass of the algorithm?
If the array were sorted using the version of quicksort presented in
lecture, what would the array look like after the first call to the
partition() method?
If the array were sorted using the version of quicksort presented in
lecture, what would the array look like after the second call to the
partition() method?
If the array were sorted using the version of mergesort presented in
lecture, what would the array look like after the completion of the
fourth call to the merge() method—the method that merges two
subarrays? Note: the merge method is the helper method; is not the
recursive mSort method.
5 points; individual-only
Important: When answering these questions, make sure to apply the
versions of these algorithms that are in the Sort class we give you. The Java
code for each algorithm can be found in our Sort
class.
Given the following array:
{14, 7, 27, 13, 24, 20, 10, 33}
If the array were sorted using quicksort, what would the array look like after the third call to the partition method?
If the array were sorted using quicksort, what would the array look like after the fourth call to the partition method?
6 points; 2 points for each part; individual-only
Given the following array:
{24, 3, 27, 13, 34, 2, 50, 12}
If the array were sorted using the version of mergesort presented
in lecture, what would the array look like after the completion of
the second call to the merge() method—the method that merges
two subarrays? Note: The merge method is the separate
helper method; is not the recursive mSort method.
What would the array look like after the completion of the
fourth call to the merge() method?
The initial call to the recursive mSort() method is made from
within the mergeSort() “wrapper” method. This initial call to
mSort() is not a recursive call, because the method is not
calling itself. Rather, all recursive calls to mSort() are
made from within mSort().
Assuming that the array has at least two elements, the initial
invocation of mSort() makes two recursive calls (which in
turn lead to other recursive calls, and so on). Starting with
the initial array above, what would the array look like after
the completion of the first of these two recursive calls?
Important
There will be no partial credit on the above questions, so please check your answers carefully!
Note: There are separate instructions at the end of Part II that you should use when submitting your work for that part of the assignment.
Submit your ps5_partI.pdf file using these steps:
If you still need to create a PDF file, open your ps5_partI file
on Google Drive, choose File->Download->PDF document, and
save the PDF file on your machine.
Login to Gradescope by clicking the link in the left-hand navigation bar, and click on the box for CS 112.
Click on the name of the assignment (PS 4: Part I) 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.)
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.
You should see a question outline along with thumbnails of the pages from your uploaded PDF. For each question in the outline:
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.
Once you have assigned pages to all of the questions 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, make a private post on Piazza with your homework before the deadline.
80 points total
15 points total; individual-only
In a file named StringRecursion.java, implement the methods described below, and then create a main() method to test these methods.
Important guidelines
for, while, or do-while loops)
is not allowed.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. static variables — i.e., variables
that are declared outside of a method. Here are the methods:
public static void printReverse(String str)
This method should use recursion to print the individual characters in
the string str in reverse order. For example,
printReverse("Terriers") should print
sreirreT
The method should not return a value.
Special cases: If the parameter is null or the empty string
(""), the method should not print anything.
public static String trim(String str)
This method should take a string str 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"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.
public static boolean isPalindrome(String str)
This method should use recursion to check if a string is a palindrome - a sequence of characters that reads the same backward as forward.
isPalindrome("hello") should return falseisPalindrome("madam") should return trueThe method should return false if the value null is passed in as
a parameter. This palindrome chacker should be case sensitive. Remember that
you may not use any built-in String methods except charAt,
length, equals, and substring.
public static String weave(String str1, String str2)
This method should use recursion to return the string that is formed by “weaving” together the characters in the strings str1 and str2 to create a single string. For example:
System.out.println( weave("aaaa", "bbbb") ); >> abababab System.out.println( weave("hello", "world") ); >> hweolrllod
If one of the strings is longer than the other, its “extra” characters — the ones
with no counterparts in the shorter string — should appear immediately after the
“woven” characters (if any) in the returned string. For example, weave("recurse", "NOW")
should return the string “rNeOcWurse”, in which the extra characters from the
first string — the characters in “urse” — come after the characters that have been woven together.
This method should not do any printing; it should simply return the resulting string.
If null is passed in for either parameter, the method should throw an IllegalArgumentException.
If the empty string (“”) is passed in for either string, the method
should return the other string. For example, weave("hello", "") should return
“hello” and weave("", "") should return “”.
public static int indexOf(char ch, String str)
This method should use recursion to find and return the index of the first occurrence of the character ch in the string str, or -1 if ch does not occur in str. For example:
System.out.println( indexOf('b', "Rabbit") ); >> 2 System.out.println( indexOf('P', "Rabbit") ); >> -1
The method should return -1 if the empty string (“”) or the value null 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!
10 points total; individual-only
In a file named ArrayRecursion.java, implement the methods described below, and then create a main() method to test these methods.
Important guidelines
for, while, or do-while loops)
is not allowed.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.static variables — i.e., variables
that are declared outside of a method.Here are the methods:
(5 points) Consider the following method, which uses iteration (a for loop) to
search for an item of type int 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) { // Always check for null references first! if (arr == null) { throw new IllegalArgumentException(); } boolean found = false; for (int i = 0; i < arr.length && !found; i++) { if (arr[i] == item) { found = true; } } return found; }
Rewrite this method so that it uses recursion instead of
iteration to search for an item which can be of any reference type
(i.e. String, Integer, etc) in an array of said reference types.
You will need to add a third parameter (i.e. 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 with each recursive call. 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
array beginning with position 2 through the end of the
array. The method header should be:
public static boolean search(_______ item, _______[] arr, int start)
(5 points) Write a Java method called reverseArrayToString() that
uses recursion to create a string of all the elements in an array,
but in reverse order. The elements of the array itself should not be reversed;
the array must be left in its original form.
Your method should have the following header:
public static String reverseArrayToString(________[] arr, int index )
where arr is a reference to the array, and index is an integer parameter
that you may use as you see fit.
The method should create and return a string representation of all the elements of the array but in reverse order. It is important that the string is created to show the elements in proper array form. For example:
String a[] = { "abc", "def", "ghi", "klm", "nop", "qrs" }; System.out.println(reverseArrayToString(a, 0));
should produce the output:
[qrs, nop, klm, ghi, def, abc]
If a null value is passed to the method instead of a valid reference to an array, the method should return the empty string.
20 points; pair-optional
This is the only problem of the assignment that you may complete with a partner. See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.
In this problem, you will write a program that solves Sudoku puzzles using recursive backtracking.
Overview
A Sudoku puzzle consists of a 9x9 grid in which some of the cells have
been filled with integers from the range 1-9. To solve the puzzle, you
fill in the remaining cells with integers from the same range, such
that each number appears exactly once in each row, column, and 3x3
subgrid.
Here is an example of an initial puzzle:

and here is its solution:

Most of the functionality of your program should go in a class called
Sudoku, which you will use to represent an individual Sudoku puzzle.
We have provided you with skeleton code for this class in the file
Sudoku.java,
which you should download and modify.
The provided code includes:
a field called grid that refers to a two-dimensional array of
integers. This array will be used to store the current contents of
the puzzle, such that grid[r][c] stores the current value in the
cell at row r, column c of the puzzle. A value of 0 is used
to indicate a blank cell.
a field called valIsFixed that refers to a two-dimensional array
of booleans. It is used to record whether the value in a given
cell is fixed (i.e., part of the original puzzle).
valIsFixed[r][c] is true if the value in the cell at row r,
column c is fixed, and false otherwise. For example,
in the original puzzle above, there is a fixed
4 in the cell at row 0, column 1 (the second cell in the top
row), and thus valIsFixed[0][1] would be true for that
puzzle.
a field called subgridHasVal that refers to a three-dimensional
array of booleans. This array allow us to determine if a given 3x3
subgrid of the puzzle already contains a given value. For example,
subgridHasVal[0][0][7] will be true if the 3x3 subgrid in the
upper-left corner of the board (a subgrid that we identify using the
indices [0][0]) already has a 7 in one of its cells. See the
comments accompanying this field for information about how the
subgrids are numbered.
partial implementations of methods called placeVal() and
removeVal() that place a value in a given cell and remove a
value from a given cell by updating the fields of the called
Sudoku object. You will need to add code to these methods to
update any new fields that you add.
a full implementation of a method called readConfig() that takes a
Scanner as its only parameter and reads in an initial
configuration of a Sudoku puzzle from that Scanner. This method
assumes that this configuration consists of nine lines of text —
one for each row of the puzzle — and that each line contains
nine integers separated by whitespace, with 0 used to indicate a
blank cell. For example, the initial configuration of the puzzle
above would begin:
0 4 0 0 0 3 7 0 0 0 8 9 7 0 0 1 0 0 ...
The method reads in the puzzle configuration and updates the
called object accordingly. You should not need to change this
method, because it calls placeVal(), and you are already
modifying that method as needed. However, we do recommend that you
read and understand this method.
the full implementation of a method called printGrid() that prints
out the current contents of the grid belonging to the called
Sudoku object.
the skeleton of a method called solveRB() that you will implement.
This is the key recursive-backtracking method, and it should
return true if a solution is found to the puzzle represented by
the called Sudoku object, and false if no solution has yet
been found (i.e., if the method is backtracking). If the initial
call to this method returns false, that means that the initial
puzzle is not valid, and therefore no solution can be found. If
there is more than one solution (which can happen if the puzzle
doesn’t have enough numbers in its initial configuration), your
code should stop after finding one of them.
The method takes a parameter n,
which is the number of the cell that the current invocation of this
method is responsible for. We recommend that you consider the cells
one row at a time, from top to bottom and left to right, which means
that they would be numbered as follows:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
Important notes:
Make sure that your solveRB() method uses the placeVal()
and removeVal() methods when updating the state of the
puzzle.
Make sure that you don’t attempt to assign a new number to
cells that are filled in the original puzzle — i.e., cells
whose values are fixed. Your solve() method will need to
skip over these cells somehow.
a full implementation of a “wrapper” method called solve() that
makes the initial call to solveRB(), and that returns the same
value that solveRB() returns. You should not change this
method.
the skeleton of a constructor. You should add the code needed to initialize the additional fields that you add.
a main() method that will be executed when you run your Sudoku
solver. You shouldn’t need to change this method, but we encourage
you to review its use of the methods of the Sudoku class. In
particular, note that it displays the puzzle after the solution is
found, and thus it isn’t necessary for your recursive-backtracking
method to display it.
Adding fields and methods
In addition to completing the methods mentioned above, you should also
add to the Sudoku class whatever additional fields or methods are
needed to maintain the state of a Sudoku puzzle and to solve it using
recursive backtracking.
To determine what additional fields are needed, ask yourself: What other fields do I need to be able to efficiently check the constraints of the puzzle – i.e., to determine whether a given value can be placed in a given cell? See our n-Queens solver for for another example of efficient constraint checking.
For full credit, your constraint-checking must be done without scanning through the rows and columns of the Sudoku board. For example, to determine if the current column contains a 5, you should not need to look at the other cells in the current column.
Make sure that you modify the placeVal() and removeVal() methods
so that they correctly update the fields that you add. In addition,
make sure that you employ proper encapsulation.
Sample puzzles
no_solution.txt,
which has no solution
multi_sol.txt,
which has multiple solutions
A sample run of the program is shown below.
Enter the name of the puzzle file: puzzle1.txt Here is the initial puzzle: ------------------------------------- | | 4 | | | | 3 | 7 | | | ------------------------------------- | | 8 | 9 | 7 | | | 1 | | | ------------------------------------- | | | | | | 4 | 2 | | | ------------------------------------- | | | | | | | | | 1 | ------------------------------------- | 6 | | | 5 | 1 | 8 | | | 9 | ------------------------------------- | 2 | | | | | | | | | ------------------------------------- | | | 5 | 3 | | | | | | ------------------------------------- | | | 6 | | | 1 | 9 | 4 | | ------------------------------------- | | | 1 | 2 | | | | 6 | | ------------------------------------- Here is the solution: ------------------------------------- | 1 | 4 | 2 | 9 | 8 | 3 | 7 | 5 | 6 | ------------------------------------- | 5 | 8 | 9 | 7 | 2 | 6 | 1 | 3 | 4 | ------------------------------------- | 7 | 6 | 3 | 1 | 5 | 4 | 2 | 9 | 8 | ------------------------------------- | 9 | 5 | 8 | 4 | 3 | 2 | 6 | 7 | 1 | ------------------------------------- | 6 | 3 | 7 | 5 | 1 | 8 | 4 | 2 | 9 | ------------------------------------- | 2 | 1 | 4 | 6 | 9 | 7 | 5 | 8 | 3 | ------------------------------------- | 4 | 7 | 5 | 3 | 6 | 9 | 8 | 1 | 2 | ------------------------------------- | 3 | 2 | 6 | 8 | 7 | 1 | 9 | 4 | 5 | ------------------------------------- | 8 | 9 | 1 | 2 | 4 | 5 | 3 | 6 | 7 | -------------------------------------
For the following problems:
Download our Sort class, making sure to save it in
your ps5 folder.
In VS Code, select the File->Open Folder or File->Open menu
option, and use the resulting dialog box to find and open your
ps5 folder. (Note: You must open the folder; it is not
sufficient to simply open the file.)
20 points total; individual-only
In a file named MergeApproach.java, implement a static method named
union that takes two arrays of integers as parameters and uses
an approach based on merging to find and return the intersection of
the two arrays – i.e., all values that are found in both arrays.
The method should have the following header
public static int[] union(int[] a1, int[] a2)
It should take two arrays of integers a1 and a2, and it should use
an approach based on merging to create and return a new array
containing the union of the values in a1 and a2 – i.e., all
values that are found in one or both of the original arrays. The
result should be in sorted order, and it should not include any
duplicate values. For example, the following test code:
int[] a1 = {10, 5, 7, 5, 9, 4}; int[] a2 = {7, 5, 15, 7, 7, 9, 10}; int[] result1 = union(a1, a2); System.out.println("result1: " + Arrays.toString(result1)); int[] a3 = {0, 2, -4, 6, 10, 8}; int[] a4 = {12, 0, -4, 8}; int[] result2 = union(a3, a4); System.out.println("result2: " + Arrays.toString(result2));
should display:
result1: [4, 5, 7, 9, 10, 15, 0, 0, 0, 0, 0, 0, 0] result2: [-4, 0, 2, 6, 8, 10, 12, 0, 0, 0]
(Note that we end up with extra 0s at the end of both of these result arrays for reasons that are discussed below.)
For full credit, your method must be as efficient as possible. See below for more details.
Required approach
Begin by creating a new array for the union, giving it a length that is the sum of the lengths of the two original arrays.
Use one of the more efficient sorting algorithms from our Sort
class to sort both of the original arrays. If you have downloaded
our Sort class into the same folder as your Problem5 class
(see the Getting started section above), you should be able to
make method calls to an appropriate method in the Sort class from
within your union method.
Find the union of the two arrays by employing an approach that is
similar to the one that we used to merge two sorted subarrays
(i.e., the approach taken by the merge method in
Sort.java)—using indices to “walk down” the two original
arrays and copy their values into the array that you created
for the union.
Important notes:
One important difference between merging and finding the union is that the union should not include any duplicates. In other words, a given number that appears in one or both of the original arrays should appear exactly once in the union. As a result, you will need to include code that skips over duplicate values as needed as you walk down the original arrays.
Your algorithm should be as efficient as possible. In particular, you should perform at most one complete pass through each of the arrays.
At the end of the method, return a reference to the array containing the union.
Add test code for your method to a main method. Recall that that
you can use the Arrays.toString() method to convert an array to
a string; import the java.util. package to gain access to the
Arrays class. In addition to the cases shown above, you
should include at least one other test case that you create.
Notes:
Because we don’t include duplicates in the result, the number
of values in the union (call it x) can be smaller
than the length of the results array (which should be the sum
of the lengths of the original arrays). In such cases, you should
end up with extra 0s at the end of the results array as shown in
both of our test cases above.
If 0 appears in one or both of the original arrays, it will also
show up earlier in the results array as part of the union, as it
does in our second example above.
If either a1 or a2 is null, the method should throw an
`IllegalArgumentException.
15 points total; individual-only
Suppose you are given an array of n integers, and you need to find
all pairs of values in the array (if any) that sum to a given integer
k. In a class named PairFinder, write code that performs this task
for you and outputs all of the pairs that it finds. For example, if
k is 12 and the array is initialized as: {10, 4, 7, 7, 8, 5, 15},
your code should output something like the following:
4 + 8 = 12 7 + 5 = 12 7 + 5 = 12
Note that we get two 7 + 5 sums because 7 appears twice in the array.
However, while the methods that you write may print a given
pair of values more than once in such cases, it is not necessary to do
so. In addition, the order in which the sums (and the terms within each
sum) are printed does not matter. If no pairs are found, the methods
do not need to print anything.
In a file named PairFinder.java, implement the following:
A static method named findPairSums() that
requires O(n²) steps to solve this problem. The method should
have the following header:
public static void findPairSums(int k, int[] arr)
In addition, you should add test code for it to a main method. You
may find it helpful to call the randomArray() method from our
SortCount class to generate test
arrays, although it also makes sense to use literal arrays that you
define.
Implement a static method named findPairSumsFaster() that
takes the same parameters as findPairSums, but that requires only
O(nlogn) steps in the average case to solve this problem.
(Hint: you should begin by sorting the array using one of the
methods from our Sort class.
Once you have done so, only O(n) additional steps are needed
to find the pairs.) Here again, you should add test code to
the main method.
Submission Checklist:
You should submit only the following files:
Here are the steps:
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.)
Add your 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.
Click the Upload button.
You should see a box saying that your submission was successful.
Click the (x) button to close that box.
The autograder will perform some tests on your files. 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 for at least some of the problems 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.
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.
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 the files contain 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.
Make sure to use these exact file names as specified or we will not be able to find your files and grade them.
Make sure that you do not try to submit a .class file or
a file with a ~ character at the end of its name.
If you make any last-minute changes to one of your Java files (e.g., adding additional comments), you should compile and run the file after you make the changes to ensure that it still runs correctly. Even seemingly minor changes can cause your code to become unrunnable.
If we are not able to compile your program, you will not receive any credit for that problem submission.
Last updated on March 3, 2026.