6 min read

    Java for DSA — Control Flow

    JavaDsaLoopsConditionalsFor-loopWhile-loopControl-flow

    3. Control Flow

    Note

    Why this matters for DSA Control flow defines the logic structure of algorithms. In DSA, loop conditions directly control space/time execution. Most optimal patterns (like Two-Pointers, Binary Search, and BFS queue traversal) are structured around carefully crafted loop and conditional skeletons.


    3.1 If-Else & Ternary Operator

    Conditionals dictate the direction of your logic.

    java
    int x = 10;
    
    // 1. If-Else-If Chain
    if (x > 0) {
        System.out.println("Positive");
    } else if (x < 0) {
        System.out.println("Negative");
    } else {
        System.out.println("Zero");
    }
    
    // 2. Ternary Operator (Inline representation of If-Else)
    // Syntax: (condition) ? value_if_true : value_if_false;
    String result = (x % 2 == 0) ? "Even" : "Odd";
    
    Tip

    Floating-Point Comparison Guard When comparing double/float values, direct comparison == can fail due to precision errors. Always check if the absolute difference is within a tiny tolerance (ϵ\epsilon):

    java
    double a = 0.1 + 0.2;
    double b = 0.3;
    if (Math.abs(a - b) < 1e-9) {
        // Treat as equal
    }
    

    3.2 Switch Expressions (Modern Java)

    When branching on a single variable with multiple discrete values (like menu options, state machine changes), a switch is cleaner than long if-else chains.

    java
    int day = 3;
    
    // Traditional Switch
    switch (day) {
        case 1:
            System.out.println("Monday");
            break;
        case 2:
            System.out.println("Tuesday");
            break;
        default:
            System.out.println("Other day");
    }
    
    // Modern Switch Expression (Java 14+ - arrow syntax)
    // No break statements needed! Prevents fall-through bugs.
    String dayName = switch (day) {
        case 1 -> "Monday";
        case 2 -> "Tuesday";
        default -> "Other day";
    };
    

    3.3 For Loops & Enhanced For-Each

    For loops are used when the number of iterations is known beforehand.

    1. Traditional for (with Index)

    java
    // Forward iteration
    for (int i = 0; i < 5; i++) {
        System.out.print(i + " "); // 0 1 2 3 4
    }
    
    // Reverse iteration (Extremely common in DP, array modifications)
    for (int i = n - 1; i >= 0; i--) {
        // ...
    }
    

    2. Enhanced For-Each Loop

    If you do not need the index of elements, use the enhanced loop. It is cleaner and prevents off-by-one errors.

    java
    int[] nums = {10, 20, 30};
    for (int val : nums) {
        System.out.println(val);
    }
    

    3. Nested Loops (2D Matrix Traversal)

    java
    int[][] matrix = {
        {1, 2},
        {3, 4}
    };
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            // Access matrix[i][j]
        }
    }
    

    3.4 While & Do-While Loops

    While loops are preferred when the termination condition changes dynamically during execution (like queue size, shrinking intervals, pointer convergence).

    java
    int count = 0;
    while (count < 5) {
        System.out.println(count);
        count++;
    }
    
    // Do-While (guaranteed to execute at least once)
    int val = 10;
    do {
        System.out.println(val); // prints 10 once, then checks condition
        val++;
    } while (val < 5);
    

    Essential DSA While-Loop Skeletons

    java
    // 1. Two-Pointers (Converging from ends)
    int left = 0, right = arr.length - 1;
    while (left < right) {
        // Logic (e.g. check sum, swap elements)
        left++;
        right--;
    }
    
    // 2. Binary Search (Dynamic range reduction)
    int low = 0, high = arr.length - 1;
    while (low <= high) {
        int mid = low + (high - low) / 2; // avoids overflow
        if (arr[mid] == target) {
            // found
        } else if (arr[mid] < target) {
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }
    
    // 3. BFS (Queue traversal)
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            Node curr = queue.poll();
            // Traverse children
        }
    }
    

    3.5 Loop Control: Break & Continue

    java
    // break: terminates the loop immediately
    for (int val : nums) {
        if (val == target) {
            break; // Stop scanning once target is found
        }
    }
    
    // continue: skips the rest of the current iteration and jumps to the next evaluation
    for (int i = 1; i <= 5; i++) {
        if (i % 2 == 0) {
            continue; // Skip even numbers
        }
        System.out.print(i + " "); // 1 3 5
    }
    
    Tip

    Labelled Break / Continue In nested loops, break only exits the innermost loop. Java allows you to define labels to break out of outer loops directly — very helpful in grid search algorithms:

    java
    outerLoop: 
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            if (grid[r][c] == target) {
                System.out.println("Found at: " + r + "," + c);
                break outerLoop; // Exits both loops!
            }
        }
    }
    

    Practice Drill

    java
    // Try implementing these:
    // 1. Print all numbers from 1 to 30 that are divisible by both 3 and 5.
    // 2. Use a while loop with two pointers to check if a sorted array contains two numbers that sum to a target.
    // 3. Use nested loops to print a triangle pattern:
    //    *
    //    **
    //    ***
    //    ****
    // 4. Find the first index of a target value in a 2D matrix using a labelled break.
    
    💡 Click for Solutions
    java
    public class ControlFlowDrill {
        public static void main(String[] args) {
            // 1. Divisible by 3 and 5
            System.out.print("Divisible by 3 and 5: ");
            for (int i = 1; i <= 30; i++) {
                if (i % 3 == 0 && i % 5 == 0) {
                    System.out.print(i + " "); // 15 30
                }
            }
            System.out.println();
    
            // 2. Two sum in sorted array
            int[] sortedArr = {1, 3, 5, 8, 12, 15};
            int targetSum = 13;
            boolean hasSum = checkTwoSum(sortedArr, targetSum);
            System.out.println("Has target sum: " + hasSum); // true (5 + 8 = 13)
    
            // 3. Triangle pattern
            int rows = 4;
            for (int i = 1; i <= rows; i++) {
                for (int j = 1; j <= i; j++) {
                    System.out.print("*");
                }
                System.out.println();
            }
    
            // 4. Find in 2D matrix with label
            int[][] matrix = {
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
            };
            int targetVal = 5;
            int foundRow = -1, foundCol = -1;
    
            searchLabel:
            for (int r = 0; r < matrix.length; r++) {
                for (int c = 0; c < matrix[r].length; c++) {
                    if (matrix[r][c] == targetVal) {
                        foundRow = r;
                        foundCol = c;
                        break searchLabel;
                    }
                }
            }
            System.out.printf("Target found at row %d, col %d\n", foundRow, foundCol); // 1, 1
        }
    
        public static boolean checkTwoSum(int[] arr, int target) {
            int left = 0;
            int right = arr.length - 1;
            while (left < right) {
                int currentSum = arr[left] + arr[right];
                if (currentSum == target) {
                    return true;
                } else if (currentSum < target) {
                    left++;
                } else {
                    right--;
                }
            }
            return false;
        }
    }
    

    ← Strings | Next → Functions