These Java exercises move from arithmetic into array processing and map-based grouping. Each problem states its inputs and expected behavior before showing a complete solution. Attempt the problem independently, then compare the algorithm and edge cases rather than only the source formatting. The solutions use Java 17 and no extra dependencies. For additional interactive practice, the Java exercise hub organizes exercises from the course, while this lesson explains how to solve three representative problems carefully.
Problem one: split a count fairly
Distribute a nonnegative number of tokens among a positive number of players. Return the base number every player receives and the number left over. For seventeen tokens and five players, each receives three and two remain. Reject invalid player counts before division. The task is about quotient and remainder, not floating-point shares. Acceptance cases include no tokens, an exact division, fewer tokens than players, and an invalid zero-player input.
Solution reasoning for quotient and remainder
Integer division gives the base allocation. The remainder tells you how many tokens remain after assigning that base to every player. Verify the invariant base times players plus leftover equals the original total, and leftover is between zero and players minus one. A fair extension might give one extra token to that many players, but the current method only reports the split. Do not quietly change the result contract while adding that extension.
Problem two: count strictly rising steps
Given an integer array, count positions where the current value is greater than its immediate predecessor. For two, five, five, nine, the count is two: two to five and five to nine. Equal neighbors do not count. Empty and one-element arrays return zero because no adjacent comparison exists. This is not the length of an increasing subsequence and does not require sorting; sorting would destroy the original sequence the task asks you to analyze.
Solution reasoning for adjacent comparisons
Start the loop at index one so every current index has a valid predecessor. Compare values[i] with values[i - 1] and increment only for a strict increase. The scan takes linear time and constant auxiliary space. A negative value is an ordinary number here, not invalid input. Test a falling sequence, repeated equal values, and alternating rises and falls. These cases distinguish a correct adjacent comparison from simply counting positive values.
Problem three: group names by first letter
Accept nonempty names and return a count for each first letter under the chosen exact-case rule. The example groups Ada and Ari under uppercase A and Bo under uppercase B. A TreeMap makes the printed key order deterministic. Decide how to treat blank or null names before implementing a general version. Lowercasing first letters would be a different normalization policy and should be specified rather than introduced as an unexplained fix.
Review a solution through its contract
Compare your answer with the supplied implementation using the acceptance cases, not by asking whether every variable has the same name. Another correct algorithm may organize code differently. Explain the termination condition, any invalid-input check, and the result for empty input. Continue with coding challenges when you can combine these skills without a supplied skeleton. For assessment, write a small JUnit test around each boundary instead of relying only on a successful main demonstration.
Practice tasks and checks
Write tests for divide(0, 4), divide(3, 5), divide(20, 5), and a zero-player rejection. Check the reconstruction invariant in every valid case. For rises, use a descending array, an all-equal array, and a single-element array, then add one alternating sequence and calculate its count by hand. For name grouping, decide whether lowercase initials join uppercase ones and implement that policy before testing mixed case. Add explicit handling for an empty name rather than waiting for charAt to fail incidentally. Finally, write one alternative solution and compare its time and storage requirements. The exercises should leave you able to justify the behavior, not merely reproduce a provided class.
Java Summary
- Derive the algorithm from a precise problem contract.
- Test empty, boundary, and invalid input according to that contract.
- Compare equivalent solutions by behavior and resource costs.
- Continue with coding challenges when these examples are clear.
Java Examples
Each example shows the code, the output it produces and what each part does.
Solve the token split
Save this program as TokenSplitExercise.java. Compile it with javac TokenSplitExercise.java and run it with java TokenSplitExercise.
Expected output:
The guard rejects invalid inputs before either division operation. Seventeen divided by five gives three with remainder two. The record keeps the two meanings named instead of returning an unexplained two-element array. Multiplying three by five and adding two reconstructs seventeen. Java 17 record accessors expose each and leftover as method calls; they do not require setters because the result is a value carrier.
public class TokenSplitExercise {
record Split(int each, int leftover) {}
static Split divide(int tokens, int players) {
if (tokens < 0 || players <= 0) throw new IllegalArgumentException("Invalid allocation");
return new Split(tokens / players, tokens % players);
}
public static void main(String[] args) {
Split split = divide(17, 5);
System.out.println(split.each());
System.out.println(split.leftover());
}
}3
2Count adjacent rises
Save this program as RisingStepsExercise.java. Compile it with javac RisingStepsExercise.java and run it with java RisingStepsExercise.
Expected output:
The loop compares five with two, five with five, and nine with five. Only the first and last comparisons are strict increases, giving two. The empty array skips the loop and returns zero. Starting at zero would make the predecessor index negative on the first iteration. The method expects a non-null array; document or validate that precondition rather than confusing null with an empty sequence.
public class RisingStepsExercise {
static int count(int[] values) {
int rises = 0;
for (int i = 1; i < values.length; i++) {
if (values[i] > values[i - 1]) rises++;
}
return rises;
}
public static void main(String[] args) {
System.out.println(count(new int[]{2, 5, 5, 9}));
System.out.println(count(new int[]{}));
}
}2
0Count groups in sorted key order
Save this program as InitialGroupsExercise.java. Compile it with javac InitialGroupsExercise.java and run it with java InitialGroupsExercise.
Expected output:
Each name supplies its first character as the map key. The first A stores one, B stores one, and the second A merges one with the existing one. TreeMap orders the Character keys, so the result prints A before B regardless of their insertion order. The constructed names are all nonempty; extending this example to arbitrary input requires a policy before charAt is called.
import java.util.Map;
import java.util.TreeMap;
public class InitialGroupsExercise {
public static void main(String[] args) {
Map<Character, Integer> counts = new TreeMap<>();
for (String name : new String[]{"Ada", "Bo", "Ari"}) {
counts.merge(name.charAt(0), 1, Integer::sum);
}
System.out.println(counts);
}
}{A=2, B=1}Java FAQ
Should I look at the solution immediately?
Try the contract and a few small cases first. If stuck, identify whether the gap is syntax or algorithm reasoning. Study the relevant step, then close the solution and write your own version to check understanding.
Is a different implementation automatically wrong?
No. Judge it against the documented behavior, input assumptions, and resource requirements. Equivalent output on one input is not enough, but different variable names or loop styles do not invalidate a correct solution.
How many exercises should I do for each topic?
Enough that you can solve a new, similar problem without looking at notes, usually three to five varied exercises per topic. If you can only solve problems you've already seen, try variations with different inputs or a changed requirement.
What should I do when my solution fails a test case?
Find the smallest input that fails and trace your code by hand or in a debugger with it. Compare the expected and actual value at each step until they first differ. Boundary values, such as zero, empty input and exact limits, are the usual suspects.
Do topic exercises prepare me for coding interviews?
They build the foundations that interview problems rely on: loops, arrays, strings, maps and clear reasoning. Follow them with timed problems in the coding challenges lesson and practise explaining your approach aloud.
Java Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
What remains after splitting seventeen tokens among five players?
Do equal adjacent values count as a rising step?
Java Quiz
2 questions to check what you learned.
Why begin the rise loop at one?
- Index zero has no predecessor
- Index zero is always invalid
- Arrays start at one
What supplies deterministic group-key output?
- TreeMap ordering
- Map by universal insertion order
- Integer::sum alone