Skip to content

Java Coding for SDET — 30 Solutions (with Explanations)

Goal: be able to WRITE each one from a blank editor AND EXPLAIN it out loud; practice by deleting the method body and re-implementing.


Q1. Reverse a String without using reverse() method

Approach: Walk from the last index to the first and append each char; O(n) time, O(n) space.

public class Q1 {
    static String reverse(String s) {
        char[] c = s.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = c.length - 1; i >= 0; i--) sb.append(c[i]);
        return sb.toString();
    }
    public static void main(String[] a) {
        System.out.println(reverse("hello")); // olleh
    }
}

Say it aloud: "I read the char array back-to-front into a StringBuilder — no built-in reverse needed."


Q2. Check if a String is a palindrome

Approach: Two pointers from both ends moving inward; stop on first mismatch. O(n) time, O(1) space.

public class Q2 {
    static boolean isPalindrome(String s) {
        int i = 0, j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i) != s.charAt(j)) return false;
            i++; j--;
        }
        return true;
    }
    public static void main(String[] a) {
        System.out.println(isPalindrome("madam")); // true
        System.out.println(isPalindrome("hello")); // false
    }
}

Say it aloud: "Two pointers converge; if any pair differs it isn't a palindrome."


Q3. Find duplicate characters in a String

Approach: Count chars in a HashMap, then print those with count > 1. O(n) time.

import java.util.*;

public class Q3 {
    static void printDuplicates(String s) {
        Map<Character, Integer> map = new LinkedHashMap<>();
        for (char c : s.toCharArray()) map.merge(c, 1, Integer::sum);
        for (Map.Entry<Character, Integer> e : map.entrySet())
            if (e.getValue() > 1) System.out.println(e.getKey() + " -> " + e.getValue());
    }
    public static void main(String[] a) {
        printDuplicates("programming"); // r->2, g->2, m->2
    }
}

Say it aloud: "I tally every char in a map, then report keys whose count exceeds one."


Q4. Count the occurrence of each character in a String

Approach: HashMap with merge to increment counts in a single pass. O(n) time.

import java.util.*;

public class Q4 {
    static Map<Character, Integer> count(String s) {
        Map<Character, Integer> map = new LinkedHashMap<>();
        for (char c : s.toCharArray()) map.merge(c, 1, Integer::sum);
        return map;
    }
    public static void main(String[] a) {
        System.out.println(count("banana")); // {b=1, a=3, n=2}
    }
}

Say it aloud: "One pass, map.merge(c, 1, Integer::sum) builds the frequency table."


Q5. Check if two Strings are anagrams

Approach: Sort both char arrays and compare (O(n log n)); or compare frequency maps. Ignore case/spaces if asked.

import java.util.*;

public class Q5 {
    static boolean isAnagram(String a, String b) {
        char[] x = a.replaceAll("\\s", "").toLowerCase().toCharArray();
        char[] y = b.replaceAll("\\s", "").toLowerCase().toCharArray();
        Arrays.sort(x); Arrays.sort(y);
        return Arrays.equals(x, y);
    }
    public static void main(String[] a) {
        System.out.println(isAnagram("listen", "silent")); // true
    }
}

Say it aloud: "Anagrams share the same letters, so sorted char arrays must be equal."


Q6. Find the first non-repeated character in a String

Approach: Build an ordered count map, then return the first key with count 1. O(n) time.

import java.util.*;

public class Q6 {
    static Character firstNonRepeated(String s) {
        Map<Character, Integer> map = new LinkedHashMap<>();
        for (char c : s.toCharArray()) map.merge(c, 1, Integer::sum);
        for (Map.Entry<Character, Integer> e : map.entrySet())
            if (e.getValue() == 1) return e.getKey();
        return null;
    }
    public static void main(String[] a) {
        System.out.println(firstNonRepeated("swiss")); // w
    }
}

Say it aloud: "LinkedHashMap keeps insertion order, so the first count-1 key is the answer."


Q7. Reverse each word in a sentence

Approach: Split on spaces, reverse each token with StringBuilder, join back. O(n) time.

public class Q7 {
    static String reverseWords(String s) {
        String[] words = s.split(" ");
        StringBuilder out = new StringBuilder();
        for (int i = 0; i < words.length; i++) {
            out.append(new StringBuilder(words[i]).reverse());
            if (i < words.length - 1) out.append(" ");
        }
        return out.toString();
    }
    public static void main(String[] a) {
        System.out.println(reverseWords("Java is fun")); // avaJ si nuf
    }
}

Say it aloud: "Split into words, reverse each word individually, keep the original word order."


Q8. Remove all whitespaces from a String

Approach: Regex replace of \s with empty; O(n) time.

public class Q8 {
    static String removeSpaces(String s) {
        return s.replaceAll("\\s", ""); // \s covers space, tab, newline
    }
    public static void main(String[] a) {
        System.out.println(removeSpaces("a b\tc\nd")); // abcd
    }
}

Say it aloud: "replaceAll(\"\\\\s\", \"\") strips every whitespace character in one shot."


Q9. Swap two numbers without using a third variable

Approach: Use arithmetic (a=a+b; b=a-b; a=a-b) or XOR to avoid a temp. O(1).

public class Q9 {
    public static void main(String[] a) {
        int x = 5, y = 9;
        x = x + y; // 14
        y = x - y; // 5
        x = x - y; // 9
        System.out.println("x=" + x + " y=" + y); // x=9 y=5
    }
}

Say it aloud: "Sum then subtract recovers each value; XOR works too but arithmetic reads clearest."


Q10. Find the factorial of a number using recursion

Approach: fact(n) = n * fact(n-1) with base case fact(0)=1. O(n) calls; use long for range.

public class Q10 {
    static long factorial(int n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1);
    }
    public static void main(String[] a) {
        System.out.println(factorial(5)); // 120
    }
}

Say it aloud: "Base case at 0/1, otherwise n times the factorial of n-1."


Q11. Check if a number is prime

Approach: Trial-divide only up to sqrt(n); handle n<2. O(sqrt(n)).

public class Q11 {
    static boolean isPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; (long) i * i <= n; i++)
            if (n % i == 0) return false;
        return true;
    }
    public static void main(String[] a) {
        System.out.println(isPrime(29)); // true
        System.out.println(isPrime(15)); // false
    }
}

Say it aloud: "A factor above sqrt(n) implies one below it, so I only test up to sqrt(n)."


Q12. Print Fibonacci series up to N terms

Approach: Iterate keeping the last two values; O(n) time, O(1) space.

public class Q12 {
    static void fibonacci(int n) {
        int a = 0, b = 1;
        for (int i = 0; i < n; i++) {
            System.out.print(a + " ");
            int next = a + b;
            a = b; b = next;
        }
    }
    public static void main(String[] a) {
        fibonacci(8); // 0 1 1 2 3 5 8 13
    }
}

Say it aloud: "I carry two running values and slide the window forward n times."


Q13. Check if a number is an Armstrong number

Approach: Sum each digit raised to the power of the digit-count; equals original if Armstrong (153 = 1^3+5^3+3^3). O(d) time.

public class Q13 {
    static boolean isArmstrong(int n) {
        int digits = String.valueOf(n).length();
        int sum = 0, temp = n;
        while (temp > 0) {
            int d = temp % 10;
            int p = 1;
            for (int k = 0; k < digits; k++) p *= d; // integer power — avoids Math.pow (double) rounding
            sum += p;
            temp /= 10;
        }
        return sum == n;
    }
    public static void main(String[] a) {
        System.out.println(isArmstrong(153)); // true
        System.out.println(isArmstrong(123)); // false
    }
}

Say it aloud: "Raise each digit to the count of digits, sum them, compare to the original."


Q14. Find the largest and smallest number in an array

Approach: Single pass tracking running min and max. O(n) time.

public class Q14 {
    static void minMax(int[] arr) {
        int min = arr[0], max = arr[0];
        for (int x : arr) {
            if (x < min) min = x;
            if (x > max) max = x;
        }
        System.out.println("min=" + min + " max=" + max);
    }
    public static void main(String[] a) {
        minMax(new int[]{3, 7, 1, 9, 4}); // min=1 max=9
    }
}

Say it aloud: "One pass, update min and max as I go — no sorting needed."


Q15. Sort an array without using sort() method

Approach: Bubble sort — swap adjacent out-of-order pairs until stable. O(n^2), fine for interview demos.

public class Q15 {
    static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++)
            for (int j = 0; j < arr.length - 1 - i; j++)
                if (arr[j] > arr[j + 1]) {
                    int t = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = t;
                }
    }
    public static void main(String[] a) {
        int[] arr = {5, 2, 8, 1, 4};
        bubbleSort(arr);
        System.out.println(java.util.Arrays.toString(arr)); // [1, 2, 4, 5, 8]
    }
}

Say it aloud: "Bubble the largest element to the end each pass by swapping neighbors."


Q16. Find duplicate elements in an array

Approach: Track seen values in a HashSet; if add returns false it's a duplicate. O(n) time.

import java.util.*;

public class Q16 {
    static Set<Integer> findDuplicates(int[] arr) {
        Set<Integer> seen = new HashSet<>(), dups = new LinkedHashSet<>();
        for (int x : arr) if (!seen.add(x)) dups.add(x);
        return dups;
    }
    public static void main(String[] a) {
        System.out.println(findDuplicates(new int[]{1, 2, 3, 2, 4, 1})); // [2, 1] (first-detected-duplicate order)
    }
}

Say it aloud: "A HashSet add returning false means I've already seen that value."


Q17. Check if two arrays are equal

Approach: Same length and same element order → Arrays.equals; if order-insensitive, sort first. O(n).

import java.util.*;

public class Q17 {
    static boolean equalIgnoringOrder(int[] a, int[] b) {
        if (a.length != b.length) return false;
        int[] x = a.clone(), y = b.clone();
        Arrays.sort(x); Arrays.sort(y);
        return Arrays.equals(x, y);
    }
    public static void main(String[] a) {
        System.out.println(Arrays.equals(new int[]{1,2,3}, new int[]{1,2,3})); // true (order-sensitive)
        System.out.println(equalIgnoringOrder(new int[]{1,2,3}, new int[]{3,2,1})); // true
    }
}

Say it aloud: "Arrays.equals checks order-sensitive equality; sorting clones first makes it order-insensitive."


Q18. Find the second highest number in an array

Approach: Single pass tracking highest and second-highest. O(n) time.

public class Q18 {
    static int secondHighest(int[] arr) {
        int first = Integer.MIN_VALUE, second = Integer.MIN_VALUE;
        for (int x : arr) {
            if (x > first) { second = first; first = x; }
            else if (x > second && x != first) second = x;
        }
        return second;
    }
    public static void main(String[] a) {
        System.out.println(secondHighest(new int[]{10, 5, 20, 8, 20})); // 10
    }
}

Say it aloud: "Two trackers; when a new max appears the old max slides into second place."


Q19. Remove duplicates from an array

Approach: Feed values into a LinkedHashSet (keeps order, drops repeats), then back to array. O(n).

import java.util.*;

public class Q19 {
    static int[] removeDuplicates(int[] arr) {
        Set<Integer> set = new LinkedHashSet<>();
        for (int x : arr) set.add(x);
        return set.stream().mapToInt(Integer::intValue).toArray();
    }
    public static void main(String[] a) {
        System.out.println(Arrays.toString(removeDuplicates(new int[]{1, 2, 2, 3, 1}))); // [1, 2, 3]
    }
}

Say it aloud: "A LinkedHashSet dedupes while preserving first-seen order."


Q20. Reverse an array

Approach: Swap symmetric pairs from both ends toward the middle. O(n) time, O(1) space.

import java.util.Arrays;

public class Q20 {
    static void reverse(int[] arr) {
        int i = 0, j = arr.length - 1;
        while (i < j) {
            int t = arr[i]; arr[i] = arr[j]; arr[j] = t;
            i++; j--;
        }
    }
    public static void main(String[] a) {
        int[] arr = {1, 2, 3, 4, 5};
        reverse(arr);
        System.out.println(Arrays.toString(arr)); // [5, 4, 3, 2, 1]
    }
}

Say it aloud: "Swap the i-th and j-th elements while the pointers move inward."


Q21. Implement a custom logic to convert String to Integer (like Integer.parseInt)

Approach: Handle optional sign, then accumulate result = result*10 + digit; throw on non-digits. O(n).

public class Q21 {
    static int parseInt(String s) {
        if (s == null || s.isEmpty()) throw new NumberFormatException("empty");
        int i = 0, sign = 1;
        if (s.charAt(0) == '-' || s.charAt(0) == '+') {
            sign = s.charAt(0) == '-' ? -1 : 1;
            i++;
        }
        long result = 0;
        for (; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c < '0' || c > '9') throw new NumberFormatException("bad char: " + c);
            result = result * 10 + (c - '0');
        }
        return (int) (sign * result);
    }
    public static void main(String[] a) {
        System.out.println(parseInt("-1234")); // -1234
    }
}

Say it aloud: "Read the sign, then build the number digit-by-digit as value*10 plus (char - '0')."


Q22. Check for balanced parentheses using Stack

Approach: Push openers; on a closer, pop and verify it matches. Balanced iff every closer matches and the stack ends empty. O(n).

import java.util.*;

public class Q22 {
    static boolean isBalanced(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        Map<Character, Character> pairs = Map.of(')', '(', ']', '[', '}', '{');
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '[' || c == '{') stack.push(c);
            else if (pairs.containsKey(c)) {
                if (stack.isEmpty() || stack.pop() != pairs.get(c)) return false;
            }
        }
        return stack.isEmpty();
    }
    public static void main(String[] a) {
        System.out.println(isBalanced("{[()]}")); // true
        System.out.println(isBalanced("{[(])}")); // false
    }
}

Say it aloud: "Push openers on a Deque; each closer must pop its matching opener, and the stack must end empty."


Q23. Implement a basic LinkedList (add, delete, print)

Approach: Singly linked nodes with head pointer; add appends to tail, delete unlinks first match. O(n) traversal.

public class Q23 {
    static class Node { int val; Node next; Node(int v) { val = v; } }

    static class LinkedList {
        Node head;
        void add(int v) {
            Node n = new Node(v);
            if (head == null) { head = n; return; }
            Node cur = head;
            while (cur.next != null) cur = cur.next;
            cur.next = n;
        }
        void delete(int v) {
            if (head == null) return;
            if (head.val == v) { head = head.next; return; }
            Node cur = head;
            while (cur.next != null && cur.next.val != v) cur = cur.next;
            if (cur.next != null) cur.next = cur.next.next;
        }
        void print() {
            for (Node cur = head; cur != null; cur = cur.next) System.out.print(cur.val + " -> ");
            System.out.println("null");
        }
    }
    public static void main(String[] a) {
        LinkedList list = new LinkedList();
        list.add(1); list.add(2); list.add(3);
        list.delete(2);
        list.print(); // 1 -> 3 -> null
    }
}

Say it aloud: "Node holds value plus next; add walks to the tail, delete relinks around the target."


Q24. Use HashMap to count word frequency in a paragraph

Approach: Split on whitespace, tally with merge; a Java 8 stream groupingBy/counting does it in one line. O(n).

import java.util.*;
import java.util.stream.*;

public class Q24 {
    static Map<String, Integer> classic(String text) {
        Map<String, Integer> map = new HashMap<>();
        for (String w : text.toLowerCase().split("\\s+")) map.merge(w, 1, Integer::sum);
        return map;
    }
    static Map<String, Long> stream(String text) {
        return Arrays.stream(text.toLowerCase().split("\\s+"))
                .collect(Collectors.groupingBy(w -> w, Collectors.counting()));
    }
    public static void main(String[] a) {
        String text = "the cat the dog the bird";
        System.out.println(classic(text)); // {the=3, cat=1, dog=1, bird=1} — HashMap: order NOT guaranteed
        System.out.println(stream(text));  // same counts; use a LinkedHashMap/TreeMap if you need stable order
    }
}

Say it aloud: "Split into words then either merge into a map or groupingBy(w, counting()) in streams."


Q25. Find common elements in two arrays/lists

Approach: Put one array in a HashSet, retainAll the other — the intersection remains. O(n+m).

import java.util.*;
import java.util.stream.*;

public class Q25 {
    static Set<Integer> common(int[] a, int[] b) {
        Set<Integer> setA = Arrays.stream(a).boxed().collect(Collectors.toSet());
        Set<Integer> setB = Arrays.stream(b).boxed().collect(Collectors.toSet());
        setA.retainAll(setB);
        return setA;
    }
    public static void main(String[] a) {
        System.out.println(common(new int[]{1,2,3,4}, new int[]{3,4,5,6})); // [3, 4]
    }
}

Say it aloud: "retainAll on one set against the other leaves exactly the intersection."


Q26. Sort a Map by values

Approach: Stream the entries, sort by a value Comparator, collect into a LinkedHashMap to keep order. O(n log n).

import java.util.*;
import java.util.stream.*;

public class Q26 {
    static <K, V extends Comparable<V>> Map<K, V> sortByValue(Map<K, V> map) {
        return map.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(
                        Map.Entry::getKey, Map.Entry::getValue,
                        (a, b) -> a, LinkedHashMap::new));
    }
    public static void main(String[] a) {
        Map<String, Integer> m = new HashMap<>();
        m.put("a", 3); m.put("b", 1); m.put("c", 2);
        System.out.println(sortByValue(m)); // {b=1, c=2, a=3}
    }
}

Say it aloud: "Stream entries, sort with comparingByValue, collect into a LinkedHashMap to preserve the new order."


Q27. Use Java 8 Stream to filter even numbers from a list

Approach: stream().filter(n -> n % 2 == 0) then collect. O(n).

import java.util.*;
import java.util.stream.*;

public class Q27 {
    static List<Integer> evens(List<Integer> nums) {
        return nums.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
    }
    public static void main(String[] a) {
        System.out.println(evens(Arrays.asList(1, 2, 3, 4, 5, 6))); // [2, 4, 6]
    }
}

Say it aloud: "A one-line stream: filter on n % 2 == 0 and collect to a list."


Q28. Find the first repeating element in an array

Approach: Scan left-to-right; the first value already in a seen-set is the answer. O(n).

import java.util.*;

public class Q28 {
    static Integer firstRepeating(int[] arr) {
        Set<Integer> seen = new HashSet<>();
        for (int x : arr) {
            if (!seen.add(x)) return x; // add fails => already seen
            }
        return null;
    }
    public static void main(String[] a) {
        System.out.println(firstRepeating(new int[]{3, 1, 4, 1, 5, 3})); // 1
    }
}

Say it aloud: "First element whose set.add returns false is the first repeat encountered."


Q29. Find missing number in a sequence (e.g., 1 to 100)

Approach: Expected sum is n(n+1)/2; subtract the actual sum to get the missing value. O(n), O(1) space.

public class Q29 {
    static int findMissing(int[] arr, int n) {
        long expected = (long) n * (n + 1) / 2;
        long actual = 0;
        for (int x : arr) actual += x;
        return (int) (expected - actual);
    }
    public static void main(String[] a) {
        // 1..10 missing 7
        System.out.println(findMissing(new int[]{1,2,3,4,5,6,8,9,10}, 10)); // 7
    }
}

Say it aloud: "Gauss's sum n(n+1)/2 minus the actual sum is exactly the missing number."


Q30. Detect a cycle in a LinkedList

Approach: Floyd's tortoise-and-hare — slow moves 1, fast moves 2; they meet iff there is a cycle. O(n) time, O(1) space.

public class Q30 {
    static class Node { int val; Node next; Node(int v) { val = v; } }

    static boolean hasCycle(Node head) {
        Node slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) return true;
        }
        return false;
    }
    public static void main(String[] a) {
        Node n1 = new Node(1), n2 = new Node(2), n3 = new Node(3);
        n1.next = n2; n2.next = n3; n3.next = n1; // cycle back to n1
        System.out.println(hasCycle(n1)); // true
    }
}

Say it aloud: "Fast moves twice as quick as slow; inside a loop it laps slow and they collide."