Topics › Basics › Things to Know in C++/Java/Python or any language

While loops

Easy TUF ID 2868 A2Z

What this covers

A while loop repeats as long as a condition holds, and it is the right tool when you cannot say in advance how many passes are needed: peel digits off a number until none are left, run Euclid’s algorithm until the remainder is zero, move two pointers until they cross. This article covers while, do-while, the while (true) loop with an exit in the middle, and the habit that keeps all of them from running forever: every pass must make measurable progress toward making the condition false. Each form is shown on a small task that comes back repeatedly on the sheets, especially in the basic maths and two-pointer sections.

while (condition) body tests the condition first and runs the body only while it is true. do body while (condition); runs the body first and tests afterwards, so the body executes at least once.

Peeling digits

The canonical while loop processes a number one digit at a time. n % 10 is the last digit and n / 10 drops it; the loop ends when n reaches 0, and nobody needs to know how many digits there were.

static long reverseNumber(long n) {
    long rev = 0;
    while (n != 0) {
        rev = rev * 10 + n % 10;
        n /= 10;
    }
    return rev;
}

The condition is n != 0 rather than n > 0 so that negative input works: for -45, n % 10 is -5, then -4, and rev becomes -54 with no special handling. The return type is long because reversing 1534236469, a valid int, gives 9646324351, which is not.

do-while: run at least once

How many digits does 0 have? One. A while (n > 0) loop would say zero, because the body never runs. do-while performs the first pass unconditionally, which is exactly the semantics the problem needs.

static int countDigits(int n) {
    long m = Math.abs((long) n);
    int count = 0;
    do {
        count++;
        m /= 10;
    } while (m > 0);
    return count;
}

The cast to long before Math.abs handles Integer.MIN_VALUE, whose absolute value does not fit in an int; without it, Math.abs returns the same negative number and the loop stops after one pass with a wrong count.

Euclid’s algorithm

The greatest common divisor satisfies gcd(a, b) = gcd(b, a mod b), and the second argument shrinks every step until it hits 0, at which point the first argument is the answer. The number of steps depends on the inputs in a way that only a while loop expresses naturally.

static int gcd(int a, int b) {
    while (b != 0) {
        int t = a % b;
        a = b;
        b = t;
    }
    return a;
}

gcd(0, 9) returns 9 after one pass, gcd(9, 0) returns 9 after zero passes. The loop runs O(log(min(a, b))) times, because the remainder at least halves every two iterations.

Base conversion

Dividing by 2 repeatedly yields the binary digits from least significant to most. Each new bit belongs in front of the ones found so far, so it is inserted at position 0. The special case for 0 exists because the loop would otherwise produce an empty string.

static String toBinary(int n) {
    if (n == 0) return "0";
    StringBuilder sb = new StringBuilder();
    while (n > 0) {
        sb.insert(0, n % 2);
        n /= 2;
    }
    return sb.toString();
}

Integer.toBinaryString does the same job in one call, and the test compares the two; writing it by hand once is how you learn what the library does.

When nobody knows the trip count

The Collatz rule, halve if even, triple and add one if odd, reaches 1 for every starting value anyone has tried, but there is no formula for how many steps it takes. A for loop has nothing to count to; while simply keeps going until the condition is met.

static int collatzSteps(long n) {
    int steps = 0;
    while (n != 1) {
        n = (n % 2 == 0) ? n / 2 : 3 * n + 1;
        steps++;
    }
    return steps;
}

6 takes 8 steps, 27 takes 111. The parameter is a long because intermediate values for 27 climb to 9232, and for larger starts they can exceed int.

Searching upward with a guard against overflow

To find the integer square root, increase r while (r + 1)^2 still fits under n. The product is formed in long: for n near Integer.MAX_VALUE, 46341 * 46341 overflows an int and would become negative, making the condition true forever.

static int floorSqrt(int n) {
    int r = 0;
    while ((long) (r + 1) * (r + 1) <= n) r++;
    return r;
}

This runs O(sqrt(n)) times, which is fine here and becomes binary search in the later “square root” problem.

while (true) with an exit in the middle

Sometimes the natural place to test for termination is after some work has been done, not before. Writing while (true) and returning (or breaking) from inside keeps the code honest about that shape instead of duplicating the work before the loop.

static int firstPowerOfTwoAbove(int n) {
    int p = 1;
    while (true) {
        if (p > n) return p;
        p *= 2;
    }
}

No statement follows the loop, and the compiler accepts the missing return because it knows a while (true) without break can only be left through the return inside. Every such loop must contain a reachable exit, and you should be able to say in one sentence why it is eventually reached: here, p doubles each pass and will exceed any n.

Two indices moving at different speeds

Merging two sorted arrays is the template for every two-pointer algorithm. Which index advances depends on the data, so the loop cannot be a for over either array alone. The condition keeps both indices in range; two short loops afterwards copy whatever one side has left.

static int[] mergeSorted(int[] a, int[] b) {
    int[] out = new int[a.length + b.length];
    int i = 0, j = 0, k = 0;
    while (i < a.length && j < b.length) {
        if (a[i] <= b[j]) out[k++] = a[i++];
        else out[k++] = b[j++];
    }
    while (i < a.length) out[k++] = a[i++];
    while (j < b.length) out[k++] = b[j++];
    return out;
}

Every pass increments exactly one of i and j, so the total work is O(n + m). out[k++] = a[i++] stores at the current k and i, then increments both; the post-increment form is idiomatic here but easy to misread, so expand it mentally once.

Edge cases and pitfalls