Back to Beginner: I/O, Arithmetic, Loops
Q2Question 2 of 30

Print even and odd numbers separately from an array

Key Concepts
  • The modulo operator % gives the remainder of integer division; num % 2 == 0 means even, num % 2 != 0 means odd.
  • In Java, the remainder of a negative dividend keeps the sign of the dividend, so -3 % 2 is -1, not 1.
  • Always test odd as num % 2 != 0, never num % 2 == 1, because the latter misclassifies negative odd numbers.
  • A single O(n) pass partitions all elements into two lists using O(n) total space.
  • The bitwise test (num & 1) != 0 is an equivalent odd check that inspects the lowest bit directly.
  • Returning two lists from a method is cleaner than printing inside the loop, making the logic unit-testable.

Definition

For each number, if dividing by two leaves no remainder it is even, otherwise it is odd: route it into the matching collection in a single pass.
  • Modulo operator (%) – returns the remainder of integer division; num % 2 is 0 for even numbers and non-zero for odd numbers.
  • Negative sign rule – in Java the remainder takes the sign of the dividend, so -3 % 2 is -1, which means testing num % 2 == 1 misses negative odds.
  • Robust odd test – num % 2 != 0 correctly identifies odd numbers regardless of sign.
  • Partitioning – one pass through the array routes each element into an evens list or an odds list, giving O(n) time and O(n) space.
  • Bitwise alternative – (num & 1) != 0 checks the lowest bit directly, which is equivalent and marginally faster.

National Bank of India assigns each account a numeric branch-batch id. For a maintenance window they process even-numbered batches on one server and odd-numbered batches on another to split the load. A clerk reads each batch id and drops it into the even tray or the odd tray.

Understanding the Concepts

What does even and odd mean?

An even number is exactly divisible by two, leaving a remainder of zero. An odd number leaves a remainder of one (or minus one for negative numbers in Java). The test num % 2 == 0 cleanly classifies each value.

How do you separate evens and odds in Java?

You loop once over the array, apply the modulo test, and add each number to either the evens list or the odds list.

JAVA
package com.bank.service;

import java.util.ArrayList;
import java.util.List;

public class BatchPartitioner {

    public static List<List<Integer>> partition(int[] batchIds) {
        List<Integer> evens = new ArrayList<>();
        List<Integer> odds = new ArrayList<>();
        for (int id : batchIds) {
            if (id % 2 == 0) {
                evens.add(id);
            } else {
                odds.add(id);
            }
        }
        return List.of(evens, odds);
    }

    public static void main(String[] args) {
        int[] batchIds = {101, 202, 303, 404, 505, 606};
        List<List<Integer>> result = partition(batchIds);
        System.out.println("Even batches: " + result.get(0));
        System.out.println("Odd batches:  " + result.get(1));
    }
}
TEXT
Even batches: [202, 404, 606]
Odd batches:  [101, 303, 505]

Why is num % 2 == 1 wrong for negative numbers?

In Java the remainder operator keeps the sign of the dividend. So -5 % 2 is -1, not 1. If you test num % 2 == 1 to detect odd numbers, every negative odd number returns -1, which does not equal 1, so it would be wrongly classified as even.

JAVA
System.out.println(-5 % 2);  // -1, not 1
System.out.println(-5 % 2 == 1);  // false (WRONG: -5 is odd)
System.out.println(-5 % 2 != 0);  // true  (CORRECT)

The robust test is always num % 2 != 0 for odd, which works for positive, negative, and zero.

How is modulo different from bitwise AND?

| Feature | num % 2 | num & 1 |
|---|---|---|
| Mechanism | integer division remainder | inspects lowest bit |
| Negative handling | result can be -1 | result is always 0 or 1 |
| Readability | clear intent | requires bit knowledge |
| Performance | compiler optimizes to same | identical after optimization |
| Odd test | != 0 | != 0 |

JAVA
int n = -7;
System.out.println(n % 2);   // -1
System.out.println(n & 1);   // 1
// Both are non-zero, so both correctly detect odd

The bitwise version always returns 0 or 1, never negative, because it masks the lowest bit. For readability I prefer the modulo form, and the compiler optimizes both identically.

What are edge cases?

Zero is even because 0 % 2 == 0. An array of all evens produces an empty odds list, and vice versa. An empty array produces two empty lists.

JAVA
int[] empty = {};
List<List<Integer>> result = partition(empty);
System.out.println(result.get(0).isEmpty()); // true
System.out.println(result.get(1).isEmpty()); // true

What about using Java Streams?

Java streams offer Collectors.partitioningBy which splits into two groups based on a predicate.

JAVA
import java.util.Map;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

int[] batchIds = {101, 202, 303, 404};
Map<Boolean, List<Integer>> parts = Arrays.stream(batchIds)
    .boxed()
    .collect(Collectors.partitioningBy(id -> id % 2 == 0));
System.out.println("Even: " + parts.get(true));
System.out.println("Odd:  " + parts.get(false));
TEXT
Even: [202, 404]
Odd:  [101, 303]

What are common mistakes?

JAVA
// Wrong: testing odd as == 1 misses negative odds
if (num % 2 == 1) { /* misses -3, -5, -7, ... */ }

// Correct: testing odd as != 0 handles all signs
if (num % 2 != 0) { /* works for -3, -5, 3, 5, ... */ }

Another mistake is printing inside the loop instead of collecting into lists. Printing is a side effect that makes the method untestable. Returning two lists lets a unit test assert the exact contents.

What should a senior engineer know?

A senior engineer returns the two lists from a pure method and keeps printing at the call site. For large-scale partitioning, such as splitting millions of transaction records by parity for parallel processing, the stream-based partitioningBy is concise and parallelizable with .parallelStream(). The key correctness point remains: always use != 0 for the odd test, never == 1.

What are common interview follow-up questions?

  • Can you partition in-place without extra lists? (Yes, use a two-pointer swap approach.)
  • How would you extend this to partition by divisibility by 3 instead of 2?
  • What is the space complexity if you only need to print, not store, the results?

Visual Overview

DIAGRAM
  ┌───────────────────────┐
  │  Input: int[] batchIds │
  └──────────┬────────────┘
             │
             ▼
  ┌───────────────────────┐
  │  evens = []           │
  │  odds  = []           │
  └──────────┬────────────┘
             │
             ▼
  ┌───────────────────────┐
  │  for each id:         │
  │    id % 2 == 0?       │
  │    Yes → evens.add    │
  │    No  → odds.add     │
  └──────────┬────────────┘
             │
             ▼
  ┌───────────────────────┐
  │  return [evens, odds] │
  └───────────────────────┘

Key Takeaway

Separating even and odd numbers is a single linear pass where you test each integer with the modulo operator. If a number divided by two leaves no remainder it is even, otherwise it is odd, and you route it into the appropriate collection. The pass is linear time, and the two result lists together hold all n elements, so the space is linear.

In a banking project at National Bank of India, this pattern split nightly batch work across two servers. Each batch carried a numeric id, and even-numbered batches went to one server while odd-numbered batches went to another to balance the load.

The nuance that matters most is negative numbers. In Java the modulo operator keeps the sign of the dividend, so a negative odd number like minus five gives a remainder of minus one, not plus one. If you tested for odd by checking whether the remainder equals one, you would wrongly classify every negative odd number as even. The robust test is num % 2 != 0, which correctly identifies odd numbers regardless of sign.

Remember one sentence: test odd as remainder-not-equal-to-zero, never remainder-equal-to-one, because Java's modulo preserves the dividend's sign.

---

Share
Use ← → arrow keys to navigate