Two sorted arrays are like two neat lines at a coffee counter — the smart move is to compare the people at the front, not rebuild the whole line from scratch.
Question: How do I merge two sorted arrays in Java?
Answer: Use two pointers, one for each array. Compare the current values, copy the smaller one into a new result array, and move that pointer forward. When one array finishes, copy the remaining tail from the other array, because it is already sorted.
Interview-Ready Answer: I’d merge them with two pointers in a single pass. At each step, I compare the current elements, write the smaller one into the result, and advance that pointer; once one array is exhausted, I copy the remaining tail from the other array. That gives me O(m + n) time and O(m + n) extra space, which is better than sorting the combined array again.
Because both inputs are already sorted, you do not need a full sort. A pointer is just an index that tells you where you are in an array. The key mental model is: the smallest remaining item must be at one of the two fronts.
i for the first array, j for the second array, and k for the result array.a[i] and b[j].result[k].k.If you want the merge to be stable, which means equal values keep their original relative order, use <= and take from the left array first when values are equal.
It shows you can exploit structure. A sorted array gives you a strong clue: every comparison should eliminate one candidate forever. That is much faster than concatenating both arrays and calling a general sort.
| Approach | Time | Space | Use when |
|---|---|---|---|
| Two pointers | O(m+n) | O(m+n) | Default choice |
| Concat + sort | O((m+n)log(m+n)) | O(m+n) | Quick but slower |
| Backward in-place merge | O(m+n) | O(1) extra | First array has room |
With arrays of length 50,000 and 50,000, the two-pointer method does at most 100,000 writes and about 99,999 comparisons. A full re-sort would do far more work, roughly proportional to 100,000 × log2(100,000), which is around 1.7 million comparison-level steps. That difference is very visible in interviews and in real systems.
When to use it: Use this whenever both inputs are already sorted and you want a sorted combined result. If the first array has extra capacity, an in-place backward merge is a nice follow-up variant: fill from the end to avoid overwriting values you have not read yet.
Real-World Story: In a checkout service, one team merged two sorted lists of line items: one from the cart and one from a pricing engine that had already ranked discounts by priority. The merge kept the page rendering fast because it avoided a full re-sort on every request.
What goes wrong when someone misunderstands the merge? A common bug is advancing the wrong pointer or forgetting to copy the leftover tail. In production, that shows up as missing discounts, duplicate entries, or occasional ArrayIndexOutOfBoundsException in logs. Users notice totals that do not match the cart, support tickets spike, and the team sees repeated item IDs or truncated arrays in telemetry.
The fix is usually simple: add tests for empty inputs, duplicate values, and one-side-exhausted cases. Those are the exact scenarios where a sloppy merge breaks.
import java.util.Arrays;
public class MergeTwoSortedArrays {
public static int[] mergeSortedArrays(int[] a, int[] b) {
// Defensive checks make failure obvious instead of producing a mysterious bug later.
if (a == null || b == null) {
throw new IllegalArgumentException("Input arrays must not be null");
}
int[] result = new int[a.length + b.length];
int i = 0; // Walks the first array
int j = 0; // Walks the second array
int k = 0; // Writes into the result array
// Keep comparing the current "front" elements until one array runs out.
while (i < a.length && j < b.length) {
// Using <= makes the merge stable: equal values from the first array stay first.
if (a[i] <= b[j]) {
result[k++] = a[i++];
} else {
result[k++] = b[j++];
}
}
// One of these loops will run, or neither will. The remaining tail is already sorted.
while (i < a.length) {
result[k++] = a[i++];
}
while (j < b.length) {
result[k++] = b[j++];
}
return result;
}
private static void printArray(String label, int[] arr) {
System.out.println(label + ": " + Arrays.toString(arr));
}
public static void main(String[] args) {
int[] first = {1, 3, 5, 9};
int[] second = {2, 3, 4, 10};
int[] empty = {};
printArray("Merged normal case", mergeSortedArrays(first, second));
printArray("Merged with empty array", mergeSortedArrays(first, empty));
// Failure path example: a null input should fail loudly and clearly.
try {
mergeSortedArrays(first, null);
} catch (IllegalArgumentException ex) {
System.out.println("Null-input check: " + ex.getMessage());
}
}
}Follow-up & Tricky Questions:
<= when comparing and choose the element from the left array first on ties. That preserves the original order of equal items from that array.Tricky / Gotcha Questions:
Common Mistakes:
<= or increment the wrong pointer at the wrong time. Fix: update the pointer only for the array you just copied from.0-length cases explicitly.Memory Hook: “Two fingers on two zipper tracks.” Look at the two front teeth, zip the smaller one into the result, and keep going until one side runs out.
Cheat Sheet:
O(m+n); space: O(m+n) for a new output array.<= for stability on equal values.Practice Tasks: