Array Fundamentals
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Solve one Java logic problem at a time, then flip for the complete explanation and program.
Java Logic Development · Chapter 09 Companion Article
Fifteen foundational array problems — reading, printing, summing, ranking, copying, reversing, and comparing — each built around a single traversal and the state it needs to carry.
Java arrays store multiple values of the same data type under one variable name. Each value is accessed through an index.
Important array fundamentals:
0.array.length - 1.0, 0.0, false, or ' '.null.ArrayIndexOutOfBoundsException.O(n) time complexity.Example: int[] numbers = {10, 20, 30, 40};
Index mapping:
| Index | Value |
|---|---|
| 0 | 10 |
| 1 | 20 |
| 2 | 30 |
| 3 | 40 |
numbers.length is 4, while the last valid index is 3.
Read multiple integer values from the user and store them in an array.
Create an array of the required size and use the loop index as the storage position. For an array of size 5: first input goes to numbers[0], second input goes to numbers[1], continue until numbers[4].
If the number of inputs is known only at runtime, read the size first and then create the array.
0 to size - 1.import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter array size: ");
int size = scanner.nextInt();
int[] numbers = new int[size];
System.out.println("Enter " + size + " elements:");
for (int i = 0; i < size; i++) {
numbers[i] = scanner.nextInt();
}
System.out.println("Array elements stored successfully.");
scanner.close();
}
}
5
12 25 8 41 19
Enter array size: Enter 5 elements:
Array elements stored successfully.
| i | Input | Stored At |
|---|---|---|
| 0 | 12 | numbers[0] |
| 1 | 25 | numbers[1] |
| 2 | 8 | numbers[2] |
| 3 | 41 | numbers[3] |
| 4 | 19 | numbers[4] |
Final array: [12, 25, 8, 41, 19]
O(n)O(n) for storing n elements.A negative array size is invalid and causes NegativeArraySizeException.
Writing i <= size instead of i < size. The last iteration would try to access an index outside the array.
Be comfortable reading both fixed-size arrays and arrays whose size is entered at runtime.
Display every value stored in an array.
Traverse the array from the first index to the last and print each element.
When the index itself is not needed, an enhanced for loop gives cleaner code.
public class Main {
public static void main(String[] args) {
int[] numbers = {12, 25, 8, 41, 19};
System.out.print("Array elements: ");
for (int number : numbers) {
System.out.print(number + " ");
}
}
}
Array elements: 12 25 8 41 19
The enhanced loop assigns each value to number:
number = 12
number = 25
number = 8
number = 41
number = 19
Each value is printed once.
An enhanced for loop automatically visits every element from beginning to end without manually managing an index.
O(n)O(1)Use index-based traversal when you need the position of an element or want to modify array values.
Trying to access numbers[numbers.length]. The final valid position is numbers.length - 1.
Know the difference between index-based for, enhanced for, and Arrays.toString().
Calculate the total of all values in an integer array. Example: [10, 20, 30, 40], sum 10 + 20 + 30 + 40 = 100.
Maintain one accumulator variable and update it while traversing the array.
sum to 0.sum.sum contains the total.public class Main {
public static void main(String[] args) {
int[] numbers = {10, 25, 15, 30, 20};
int sum = 0;
for (int number : numbers) {
sum += number;
}
System.out.println("Sum = " + sum);
}
}
Sum = 100
| Element | Previous Sum | New Sum |
|---|---|---|
| 10 | 0 | 10 |
| 25 | 10 | 35 |
| 15 | 35 | 50 |
| 30 | 50 | 80 |
| 20 | 80 | 100 |
Every array value contributes exactly once to the accumulator.
O(n)O(1)For very large integer values, an int sum may overflow. Use long when the possible total can exceed the int range.
Resetting sum inside the loop. Incorrect idea:
for (int number : numbers) {
int sum = 0;
}
The accumulator must exist outside the loop so it retains the previous total.
Summation is the foundation of many later problems such as averages, prefix sums, subarray sums, and cumulative statistics.
Find the arithmetic mean of all array elements. Formula: Average = Sum of Elements / Number of Elements. For [10, 20, 30, 40], average is 100 / 4 = 25.0.
Use floating-point division. Integer division can remove the decimal part.
double.public class Main {
public static void main(String[] args) {
int[] numbers = {15, 22, 31, 18, 24};
int sum = 0;
for (int number : numbers) {
sum += number;
}
double average = (double) sum / numbers.length;
System.out.println("Average = " + average);
}
}
Average = 22.0
Sum: 15 + 22 + 31 + 18 + 24 = 110. Length: 5. Calculation: 110.0 / 5 = 22.0.
Without the cast:
int sum = 7;
int length = 2;
double average = sum / length;
sum / length performs integer division first: 7 / 2 = 3. The resulting double becomes 3.0, not 3.5. Using (double) sum / length produces the expected decimal result.
O(n)O(1)An empty array has no mathematical average. Dividing by its length should therefore be avoided.
When numerical results may contain fractions, always inspect the operand types before performing division.
Find the largest value present in an array. Example: [14, 52, 7, 31, 26], maximum 52.
Instead of starting with 0, initialize the maximum with the first array element.
public class Main {
public static void main(String[] args) {
int[] numbers = {-12, -5, -27, -3, -19};
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
System.out.println("Maximum = " + max);
}
}
Maximum = -3
| Current Value | Current Maximum | Action |
|---|---|---|
| -12 | -12 | Initial value |
| -5 | -5 | Update |
| -27 | -5 | No change |
| -3 | -3 | Update |
| -19 | -3 | No change |
For an array containing only negative values, 0 would incorrectly remain larger than every actual element.
O(n)O(1)The array must contain at least one element before accessing numbers[0].
A maximum can be found in one traversal. Sorting the entire array only to obtain the maximum is unnecessary and costs O(n log n).
Find the smallest element in an array.
Keep the best minimum found so far and replace it whenever a smaller value appears.
min.1.min.min whenever a smaller element is found.public class Main {
public static void main(String[] args) {
int[] numbers = {42, 17, 63, 9, 28};
int min = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] < min) {
min = numbers[i];
}
}
System.out.println("Minimum = " + min);
}
}
Minimum = 9
| Value | min After Comparison |
|---|---|
| 42 | 42 |
| 17 | 17 |
| 63 | 17 |
| 9 | 9 |
| 28 | 9 |
min always represents the smallest element encountered up to the current position.
O(n)O(1)Sorting an array when only the minimum value is required.
Maximum and minimum can also be found together in one traversal when both values are required.
Find the second-largest distinct value without sorting the array. For [20, 45, 12, 45, 31], distinct values in descending order are 45, 31, 20, 12. Therefore Second Largest = 31.
Maintain two values: the largest and second largest found so far.
largest: move the old largest into secondLargest, then store the current value in largest.largest but greater than secondLargest, update only secondLargest.public class Main {
public static void main(String[] args) {
int[] numbers = {20, 45, 12, 45, 31};
Integer largest = null;
Integer secondLargest = null;
for (int number : numbers) {
if (largest == null || number > largest) {
secondLargest = largest;
largest = number;
} else if (number < largest && (secondLargest == null || number > secondLargest)) {
secondLargest = number;
}
}
if (secondLargest != null) {
System.out.println("Second largest = " + secondLargest);
} else {
System.out.println("No second largest distinct element.");
}
}
}
Second largest = 31
| Number | Largest | Second Largest |
|---|---|---|
| 20 | 20 | null |
| 45 | 45 | 20 |
| 12 | 45 | 20 |
| 45 | 45 | 20 |
| 31 | 45 | 31 |
It prevents another occurrence of the maximum value from becoming the second-largest distinct value. For [50, 50, 40], the second-largest distinct value is 40, not 50.
O(n)O(1)[7, 7, 7]: no second-largest distinct value.Sorting first when the interviewer specifically asks for an O(n) solution.
Clarify whether "second largest" means the second array position after sorting or the second distinct largest value.
Find the second-smallest distinct value in one traversal. For [8, 3, 5, 3, 11], distinct sorted values are 3, 5, 8, 11, so Second Smallest = 5.
Track the smallest two distinct values while scanning the array.
smallest: move the old smallest to secondSmallest, then replace smallest.secondSmallest only when the value is greater than smallest and smaller than the existing second smallest.public class Main {
public static void main(String[] args) {
int[] numbers = {8, 3, 5, 3, 11};
Integer smallest = null;
Integer secondSmallest = null;
for (int number : numbers) {
if (smallest == null || number < smallest) {
secondSmallest = smallest;
smallest = number;
} else if (number > smallest && (secondSmallest == null || number < secondSmallest)) {
secondSmallest = number;
}
}
if (secondSmallest != null) {
System.out.println("Second smallest = " + secondSmallest);
} else {
System.out.println("No second smallest distinct element.");
}
}
}
Second smallest = 5
| Number | Smallest | Second Smallest |
|---|---|---|
| 8 | 8 | null |
| 3 | 3 | 8 |
| 5 | 3 | 5 |
| 3 | 3 | 5 |
| 11 | 3 | 5 |
O(n)O(1)Sorting would reorganize the whole array even though only two values are required.
Not excluding duplicates of the minimum value.
The second-smallest problem tests whether you can maintain multiple state variables during a single traversal.
Count how many elements in an array are even. A number is even when number % 2 == 0.
Test every element independently and increment the counter only when the remainder is zero.
public class Main {
public static void main(String[] args) {
int[] numbers = {12, 7, 18, 21, 30, 5};
int evenCount = 0;
for (int number : numbers) {
if (number % 2 == 0) {
evenCount++;
}
}
System.out.println("Even elements = " + evenCount);
}
}
Even elements = 3
| Value | Even? | Count |
|---|---|---|
| 12 | Yes | 1 |
| 7 | No | 1 |
| 18 | Yes | 2 |
| 21 | No | 2 |
| 30 | Yes | 3 |
| 5 | No | 3 |
Zero is an even number because 0 % 2 == 0. Negative values also follow the same parity rule. Examples:
-8 % 2 == 0
-7 % 2 != 0
O(n)O(1)The same traversal pattern can count numbers satisfying almost any condition.
Count the elements that are not divisible by 2.
Usenumber % 2 != 0rather than checking only for a remainder of1.
This matters because Java can produce a negative remainder for negative odd numbers. Example: -7 % 2 = -1. Therefore number % 2 == 1 is not a reliable general odd check.
public class Main {
public static void main(String[] args) {
int[] numbers = {-7, 4, 13, -9, 20, 11};
int oddCount = 0;
for (int number : numbers) {
if (number % 2 != 0) {
oddCount++;
}
}
System.out.println("Odd elements = " + oddCount);
}
}
Odd elements = 4
| Value | Remainder by 2 | Odd? | Count |
|---|---|---|---|
| -7 | -1 | Yes | 1 |
| 4 | 0 | No | 1 |
| 13 | 1 | Yes | 2 |
| -9 | -1 | Yes | 3 |
| 20 | 0 | No | 3 |
| 11 | 1 | Yes | 4 |
O(n)O(1)Using number % 2 == 1, which can fail for negative odd integers.
number % 2 != 0 is the safer general-purpose condition for odd integers in Java.
Count positive, negative, and zero values separately. Classification:
number > 0 -> Positive
number < 0 -> Negative
number == 0 -> Zero
Zero belongs to neither the positive nor negative group.
if-else if-else chain.public class Main {
public static void main(String[] args) {
int[] numbers = {-8, 12, 0, -3, 17, 6, 0};
int positiveCount = 0;
int negativeCount = 0;
int zeroCount = 0;
for (int number : numbers) {
if (number > 0) {
positiveCount++;
} else if (number < 0) {
negativeCount++;
} else {
zeroCount++;
}
}
System.out.println("Positive elements = " + positiveCount);
System.out.println("Negative elements = " + negativeCount);
System.out.println("Zero elements = " + zeroCount);
}
}
Positive elements = 3
Negative elements = 2
Zero elements = 2
| Value | Category |
|---|---|
| -8 | Negative |
| 12 | Positive |
| 0 | Zero |
| -3 | Negative |
| 17 | Positive |
| 6 | Positive |
| 0 | Zero |
Final counters:
Positive = 3
Negative = 2
Zero = 2
The three conditions are mutually exclusive. One number cannot belong to more than one category.
O(n)O(1)Treating zero as positive because it is not negative.
This problem demonstrates classification during traversal. The same technique is useful for partitioning and frequency analysis.
Create a separate array containing the same values as an existing array.
This does not create an independent copy: int[] copy = original; It only copies the reference. Both variables point to the same array object.
Create a new array and copy individual elements into it.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] original = {10, 20, 30, 40};
int[] copy = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i];
}
copy[0] = 99;
System.out.println("Original: " + Arrays.toString(original));
System.out.println("Copy: " + Arrays.toString(copy));
}
}
Original: [10, 20, 30, 40]
Copy: [99, 20, 30, 40]
After copying:
original = [10, 20, 30, 40]
copy = [10, 20, 30, 40]
Then copy[0] = 99. Result:
original = [10, 20, 30, 40]
copy = [99, 20, 30, 40]
The original remains unchanged because the arrays are separate objects.
int[] copy = original.clone(); or int[] copy = Arrays.copyOf(original, original.length); or System.arraycopy(original, 0, copy, 0, original.length);
O(n)O(n)int[] a = {1, 2, 3};
int[] b = a;
Here, a and b refer to the same array. Changing b[0] = 100; also changes what is observed through a.
Be ready to explain the difference between copying an array reference and copying array contents.
Reverse the order of array elements. Before: [10, 20, 30, 40, 50]. After: [50, 40, 30, 20, 10].
Swap elements from opposite ends and move both positions toward the center.
Start with:
left = 0
right = array.length - 1
While left < right, perform swap(array[left], array[right]), then:
left++
right--
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
int left = 0;
int right = numbers.length - 1;
while (left < right) {
int temp = numbers[left];
numbers[left] = numbers[right];
numbers[right] = temp;
left++;
right--;
}
System.out.println("Reversed array: " + Arrays.toString(numbers));
}
}
Reversed array: [50, 40, 30, 20, 10]
Initial: [10, 20, 30, 40, 50]. First swap (index 0 <-> index 4): [50, 20, 30, 40, 10]. Second swap (index 1 <-> index 3): [50, 40, 30, 20, 10]. Now:
left = 2
right = 2
The condition left < right becomes false.
Every swap places two elements in their final reversed positions.
O(n)O(1) because the reversal happens in place.Create another array and copy elements from the original in reverse order. That approach also takes O(n) time but requires O(n) additional memory.
Traversing the entire array while swapping opposite elements. Doing so can reverse the array once and then reverse it back.
The two-pointer technique used here appears frequently in array, string, palindrome, and partitioning problems.
Compare two arrays element by element and identify where they differ. This is different from only returning a final true or false equality result. A comparison can explain mismatched values or lengths. Example:
First = [10, 20, 30, 40]
Second = [10, 25, 30, 50]
Differences exist at indexes 1 and 3.
Compare elements only up to the smaller array length, then separately check whether the lengths differ.
public class Main {
public static void main(String[] args) {
int[] first = {10, 20, 30, 40};
int[] second = {10, 25, 30, 50};
int limit = Math.min(first.length, second.length);
boolean differenceFound = false;
for (int i = 0; i < limit; i++) {
if (first[i] != second[i]) {
System.out.println("Difference at index " + i + ": " + first[i] + " != " + second[i]);
differenceFound = true;
}
}
if (first.length != second.length) {
System.out.println("Array lengths are different.");
differenceFound = true;
}
if (!differenceFound) {
System.out.println("No differences found.");
}
}
}
Difference at index 1: 20 != 25
Difference at index 3: 40 != 50
| Index | First | Second | Result |
|---|---|---|---|
| 0 | 10 | 10 | Same |
| 1 | 20 | 25 | Different |
| 2 | 30 | 30 | Same |
| 3 | 40 | 50 | Different |
If the arrays have different lengths, looping through the longer array could access a position that does not exist in the shorter one. For:
first = [1, 2, 3]
second = [1, 2]
only indexes 0 and 1 can safely be compared directly.
O(min(n, m)) where n and m are the two array lengths.O(1)Always clarify the required meaning.
Do not assume "compare arrays" always means equality. Understand whether the interviewer wants mismatch detection, ordering, or content comparison.
Determine whether two arrays contain exactly the same values in exactly the same order. Arrays are equal when their lengths are equal and every corresponding element is equal. Example:
[10, 20, 30]
[10, 20, 30]
Result: Equal. But:
[10, 20, 30]
[30, 20, 10]
Result: Not Equal. The elements are the same, but their positions are different.
Check the lengths before comparing individual values.
public class Main {
public static void main(String[] args) {
int[] first = {15, 25, 35, 45};
int[] second = {15, 25, 35, 45};
boolean equal = true;
if (first.length != second.length) {
equal = false;
} else {
for (int i = 0; i < first.length; i++) {
if (first[i] != second[i]) {
equal = false;
break;
}
}
}
System.out.println("Arrays equal = " + equal);
}
}
Arrays equal = true
Length check:
first.length = 4
second.length = 4
Lengths match. Element comparisons:
first[0] == second[0] -> 15 == 15
first[1] == second[1] -> 25 == 25
first[2] == second[2] -> 35 == 35
first[3] == second[3] -> 45 == 45
No mismatch occurs, so equal remains true.
The break statement stops comparison immediately after the first mismatch. There is no need to inspect the remaining elements once inequality has been established.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] first = {15, 25, 35, 45};
int[] second = {15, 25, 35, 45};
System.out.println("Arrays equal = " + Arrays.equals(first, second));
}
}
Arrays equal = true
For arrays:
int[] first = {1, 2, 3};
int[] second = {1, 2, 3};
The expression first == second checks whether both variables refer to the exact same array object. It does not compare their element values. Use Arrays.equals(first, second) for one-dimensional array content comparison.
O(n) in the worst case.O(1)Use Arrays.deepEquals() when comparing nested object-array structures where deep element comparison is required.
A common Java interview question asks for the difference between ==, Arrays.equals(), and Arrays.deepEquals().
Most fundamental array problems can be reduced to a small set of traversal patterns.
| Problem Type | State Maintained |
|---|---|
| Print elements | Current element |
| Sum | Running total |
| Average | Sum and length |
| Maximum | Largest value so far |
| Minimum | Smallest value so far |
| Second largest | Largest + second largest |
| Second smallest | Smallest + second smallest |
| Count values | Counter |
| Classification | Multiple counters |
| Copy | Source and destination index |
| Reverse | Left and right pointers |
| Equality | Equality flag |
| Comparison | Mismatch information |
Recognizing the pattern is more valuable than memorizing individual programs.
Use an index-based loop when the position matters:
for (int i = 0; i < numbers.length; i++) {
System.out.println("Index " + i + " = " + numbers[i]);
}
Useful for reversing an array, updating elements, comparing corresponding indexes, copying by position, finding an element's index, and accessing neighboring elements.
Use an enhanced for loop when only values matter:
for (int number : numbers) {
System.out.println(number);
}
Useful for sum, count, maximum, minimum, and simple printing. An enhanced loop does not directly expose the current array index.
For int[] numbers = new int[5];, array length is numbers.length = 5. Valid indexes:
0
1
2
3
4
Invalid index: 5. Therefore, the standard traversal condition is i < numbers.length, not i <= numbers.length.
int[] numbers = {10, 20, 30, 40}; Java automatically determines the length.
int[] numbers = new int[4];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
For int[] numbers = new int[3];, initial contents are [0, 0, 0]. Common primitive defaults:
| Type | Default Value |
|---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0 |
char | ' ' |
boolean | false |
Reference-type array elements default to null.
int[] numbers = {}; Its length is 0. Traversal is safe:
for (int number : numbers) {
System.out.println(number);
}
The loop simply executes zero times. However, this is unsafe: int max = numbers[0]; There is no index 0. Problems such as maximum, minimum, second largest, and average therefore require meaningful handling for empty input.
[50]. Valid results: Sum = 50, Average = 50.0, Maximum = 50, Minimum = 50. But there is no second distinct largest or second distinct smallest value.
For [10, 20, 20, 30, 30], duplicates do not affect basic sum or count logic, but they matter when finding distinct values such as second largest.
Algorithms should not assume values are positive. For example, [-20, -5, -12] has maximum -5. Initializing max = 0 would produce an incorrect result.
Incorrect: for (int i = 0; i <= numbers.length; i++). Correct: for (int i = 0; i < numbers.length; i++).
Incorrect: numbers[1] for accessing the first element. The first element is numbers[0].
If numbers.length == 5, the last index is 4.
Risky: int max = 0; Better: int max = numbers[0];
Risky: double average = sum / numbers.length; Better: double average = (double) sum / numbers.length;
Incorrect for content comparison: first == second. Correct: Arrays.equals(first, second).
This does not make an independent copy: int[] copy = original; Use an actual copying operation when separate arrays are required.
Finding maximum, minimum, second maximum, or second minimum does not normally require sorting. A direct traversal usually gives O(n) time compared with O(n log n) sorting.
| Operation | Time | Extra Space |
|---|---|---|
| Read Array Elements | O(n) | O(n) |
| Print Array Elements | O(n) | O(1) |
| Sum Elements | O(n) | O(1) |
| Average Elements | O(n) | O(1) |
| Maximum Element | O(n) | O(1) |
| Minimum Element | O(n) | O(1) |
| Second Largest | O(n) | O(1) |
| Second Smallest | O(n) | O(1) |
| Count Even Elements | O(n) | O(1) |
| Count Odd Elements | O(n) | O(1) |
| Count Positive/Negative | O(n) | O(1) |
| Copy Array | O(n) | O(n) |
| Reverse In Place | O(n) | O(1) |
| Compare Arrays | O(min(n,m)) | O(1) |
| Check Equality | O(n) | O(1) |
The array itself requires O(n) storage. "Extra space" refers to additional working memory used by the algorithm.
The java.util.Arrays class provides useful array operations.
Arrays.toString(numbers)
Arrays.equals(first, second)
Arrays.copyOf(numbers, numbers.length)
Arrays.copyOfRange(numbers, 1, 4)
Arrays.sort(numbers)
Arrays.fill(numbers, 10)
Arrays.binarySearch(numbers, target)
These methods are useful in production code, but manually implementing fundamental operations is valuable when learning logic or answering coding interview questions.
A learner should be able to explain these points without relying only on memorized code:
0.length - 1.O(n) time.== and Arrays.equals() behave differently.After understanding the fundamentals, useful extensions include:
Arrays.equals().These variations build directly on traversal, comparison, accumulation, counters, and two-pointer logic introduced in this chapter.
numbers.length instead of hard-coding array bounds.Arrays.equals() for content equality rather than ==.O(n) traversal over sorting when sorting is not necessary for the required result.